From 306377a7bebecfd1e7851a144470b899ad51b310 Mon Sep 17 00:00:00 2001
From: Francesco Grazioso <40018163+FrancescoGrazioso@users.noreply.github.com>
Date: Sat, 1 Jun 2024 11:59:11 +0200
Subject: [PATCH 01/13] Feat/app api and frontend (#136)
* minor fixes
* created basic django app
* add django dependency
* created basic search endpoint
* created retrieve method for search
* remove retrieve
* start implementing download endpoint (only movie for now)
* start implementing episode info for series
* finished get_episodes_info
* minor fixes
* add download anime episode
* start implementing download for tv series
* refactor methods
* finished download endpoint (will implement possibility to download single episodes of season in tv series)
* new domain and black on project
* start
* add cors
* add start gui command
* add gui for search
* edited .gitignore
* create component for media details
* better UX/UI
* edited anime episode to stream response (better experience)
* implemented UI for media details (TODO add download capabilities)
* fix poster fetching
* minor fixes
* fix cors error
* start implementing download
* fix typing on anime movies
* refactor
* refactor + add download OVA
* add plot for all anime types
* add download for all anime episodes
* add download all tv series episodes
* fix crach if localStorage is undefined
* moved download logic in separeted file
* fix wrong index passed while downloading tv series
* fix style searchbar
* add loader to search button and add enter listener while searching
* remove dependency from loading episodes to download all in anime series
* add function to download selected episodes for anime
* add sh command to kill gui
* fix messages in kill_gui.sh
* start implementing download select episodes for tv series (to be tested) + run black and eslint
* start refactoring to version 2.0
* start implementing preview endpoint
---
.gitignore | 13 +-
Src/Api/Animeunity/Core/Class/EpisodeType.py | 15 +
Src/Api/Animeunity/Core/Class/PreviewType.py | 13 +
Src/Api/Animeunity/Core/Class/SearchType.py | 23 +
.../Core/Class/EpisodeType.py | 28 +
.../Core/Class/PreviewType.py | 13 +
.../Core/Class/SearchType.py | 34 +
api/__init__.py | 0
api/api/__init__.py | 0
api/api/asgi.py | 16 +
api/api/settings.py | 140 +
api/api/urls.py | 24 +
api/api/wsgi.py | 16 +
api/endpoints/__init__.py | 0
api/endpoints/admin.py | 3 +
api/endpoints/apps.py | 6 +
api/endpoints/migrations/__init__.py | 0
api/endpoints/models.py | 3 +
api/endpoints/tests.py | 3 +
api/endpoints/urls.py | 10 +
api/endpoints/views.py | 241 ++
api/manage.py | 24 +
config.json | 2 +-
frontend/.eslintrc.cjs | 15 +
frontend/.gitignore | 30 +
frontend/.prettierrc.json | 8 +
frontend/.vscode/extensions.json | 7 +
frontend/README.md | 39 +
frontend/env.d.ts | 1 +
frontend/index.html | 13 +
frontend/package-lock.json | 3225 +++++++++++++++++
frontend/package.json | 36 +
frontend/public/favicon.ico | Bin 0 -> 4286 bytes
frontend/src/App.vue | 36 +
frontend/src/api/api.ts | 81 +
frontend/src/api/interfaces.ts | 64 +
frontend/src/api/utils.ts | 63 +
frontend/src/assets/base.css | 86 +
frontend/src/assets/logo.svg | 1 +
frontend/src/assets/main.css | 35 +
frontend/src/components/Card.vue | 92 +
frontend/src/components/Toggle.vue | 105 +
frontend/src/main.ts | 11 +
frontend/src/router/index.ts | 30 +
frontend/src/views/Details.vue | 335 ++
frontend/src/views/HomeView.vue | 176 +
frontend/tsconfig.app.json | 14 +
frontend/tsconfig.json | 11 +
frontend/tsconfig.node.json | 19 +
frontend/vite.config.ts | 16 +
kill_gui.sh | 29 +
requirements.txt | 9 +-
start_gui.sh | 23 +
53 files changed, 5234 insertions(+), 3 deletions(-)
create mode 100644 api/__init__.py
create mode 100644 api/api/__init__.py
create mode 100644 api/api/asgi.py
create mode 100644 api/api/settings.py
create mode 100644 api/api/urls.py
create mode 100644 api/api/wsgi.py
create mode 100644 api/endpoints/__init__.py
create mode 100644 api/endpoints/admin.py
create mode 100644 api/endpoints/apps.py
create mode 100644 api/endpoints/migrations/__init__.py
create mode 100644 api/endpoints/models.py
create mode 100644 api/endpoints/tests.py
create mode 100644 api/endpoints/urls.py
create mode 100644 api/endpoints/views.py
create mode 100755 api/manage.py
create mode 100644 frontend/.eslintrc.cjs
create mode 100644 frontend/.gitignore
create mode 100644 frontend/.prettierrc.json
create mode 100644 frontend/.vscode/extensions.json
create mode 100644 frontend/README.md
create mode 100644 frontend/env.d.ts
create mode 100644 frontend/index.html
create mode 100644 frontend/package-lock.json
create mode 100644 frontend/package.json
create mode 100644 frontend/public/favicon.ico
create mode 100644 frontend/src/App.vue
create mode 100644 frontend/src/api/api.ts
create mode 100644 frontend/src/api/interfaces.ts
create mode 100644 frontend/src/api/utils.ts
create mode 100644 frontend/src/assets/base.css
create mode 100644 frontend/src/assets/logo.svg
create mode 100644 frontend/src/assets/main.css
create mode 100644 frontend/src/components/Card.vue
create mode 100644 frontend/src/components/Toggle.vue
create mode 100644 frontend/src/main.ts
create mode 100644 frontend/src/router/index.ts
create mode 100644 frontend/src/views/Details.vue
create mode 100644 frontend/src/views/HomeView.vue
create mode 100644 frontend/tsconfig.app.json
create mode 100644 frontend/tsconfig.json
create mode 100644 frontend/tsconfig.node.json
create mode 100644 frontend/vite.config.ts
create mode 100755 kill_gui.sh
create mode 100755 start_gui.sh
diff --git a/.gitignore b/.gitignore
index be44e50..69e9099 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,14 @@ local_settings.py
db.sqlite3
db.sqlite3-journal
+
+# Vue stuff:
+frontend/dist/
+frontend/node_modules/
+frontend/npm-debug.log
+frontend/.vite/
+frontend/.vscode/
+
# Jupyter Notebook
.ipynb_checkpoints
@@ -55,4 +63,7 @@ env.bak/
venv.bak/
# Other
-Video
\ No newline at end of file
+Video
+.idea/
+.vscode/
+.DS_Store
diff --git a/Src/Api/Animeunity/Core/Class/EpisodeType.py b/Src/Api/Animeunity/Core/Class/EpisodeType.py
index 14b9694..f583914 100644
--- a/Src/Api/Animeunity/Core/Class/EpisodeType.py
+++ b/Src/Api/Animeunity/Core/Class/EpisodeType.py
@@ -45,6 +45,21 @@ class Episode:
def __str__(self):
return f"Episode(id={self.id}, number={self.number}, name='{self.name}', plot='{self.plot}', duration={self.duration} sec)"
+
+ def to_dict(self) -> Dict[str, Any]:
+ return {
+ "id": self.id,
+ "number": self.number,
+ "name": self.name,
+ "plot": self.plot,
+ "duration": self.duration,
+ "scws_id": self.scws_id,
+ "season_id": self.season_id,
+ "created_by": self.created_by,
+ "created_at": self.created_at,
+ "updated_at": self.updated_at,
+ "images": [image.__dict__ for image in self.images]
+ }
class EpisodeManager:
diff --git a/Src/Api/Animeunity/Core/Class/PreviewType.py b/Src/Api/Animeunity/Core/Class/PreviewType.py
index 28d741e..7b80b0a 100644
--- a/Src/Api/Animeunity/Core/Class/PreviewType.py
+++ b/Src/Api/Animeunity/Core/Class/PreviewType.py
@@ -60,4 +60,17 @@ class PreviewManager:
images_str = "\n".join(str(image) for image in self.images)
return f"Title: ID={self.id}, Type={self.type}, Runtime={self.runtime}, Release Date={self.release_date}, Quality={self.quality}, Plot={self.plot}, Seasons Count={self.seasons_count}\nGenres:\n{genres_str}\nPreview:\n{self.preview}\nImages:\n{images_str}"
+ def to_dict(self):
+ return {
+ "id": self.id,
+ "type": self.type,
+ "runtime": self.runtime,
+ "release_date": self.release_date,
+ "quality": self.quality,
+ "plot": self.plot,
+ "seasons_count": self.seasons_count,
+ "genres": [genre.__dict__ for genre in self.genres],
+ "preview": self.preview.__dict__,
+ "images": [image.__dict__ for image in self.images]
+ }
diff --git a/Src/Api/Animeunity/Core/Class/SearchType.py b/Src/Api/Animeunity/Core/Class/SearchType.py
index 6c492bf..4e3c50f 100644
--- a/Src/Api/Animeunity/Core/Class/SearchType.py
+++ b/Src/Api/Animeunity/Core/Class/SearchType.py
@@ -37,10 +37,33 @@ class MediaItem:
self.last_air_date: str = data.get('last_air_date')
self.seasons_count: int = data.get('seasons_count')
self.images: List[Image] = [Image(image_data) for image_data in data.get('images', [])]
+ self.comment: str = data.get('comment')
+ self.plot: str = data.get('plot')
def __str__(self):
return f"MediaItem(id={self.id}, slug='{self.slug}', name='{self.name}', type='{self.type}', score='{self.score}', sub_ita={self.sub_ita}, last_air_date='{self.last_air_date}', seasons_count={self.seasons_count}, images={self.images})"
+ @property
+ def to_dict(self) -> dict:
+ """
+ Convert the MediaItem to a dictionary.
+
+ Returns:
+ dict: The MediaItem as a dictionary.
+ """
+ return {
+ "id": self.id,
+ "slug": self.slug,
+ "name": self.name,
+ "type": self.type.upper(),
+ "score": self.score,
+ "sub_ita": self.sub_ita,
+ "last_air_date": self.last_air_date,
+ "seasons_count": self.seasons_count,
+ "images": [image.__dict__ for image in self.images],
+ "comment": self.comment,
+ "plot": self.plot
+ }
class MediaManager:
def __init__(self):
diff --git a/Src/Api/Streamingcommunity/Core/Class/EpisodeType.py b/Src/Api/Streamingcommunity/Core/Class/EpisodeType.py
index 468e98b..8857726 100644
--- a/Src/Api/Streamingcommunity/Core/Class/EpisodeType.py
+++ b/Src/Api/Streamingcommunity/Core/Class/EpisodeType.py
@@ -27,6 +27,19 @@ class Image:
def __str__(self):
return f"Image(id={self.id}, filename='{self.filename}', type='{self.type}', imageable_type='{self.imageable_type}', url='{self.url}')"
+
+ def to_dict(self) -> Dict[str, Any]:
+ return {
+ 'id': self.id,
+ 'filename': self.filename,
+ 'type': self.type,
+ 'imageable_type': self.imageable_type,
+ 'imageable_id': self.imageable_id,
+ 'created_at': self.created_at,
+ 'updated_at': self.updated_at,
+ 'original_url_field': self.original_url_field,
+ 'url': self.url
+ }
class Episode:
@@ -45,6 +58,21 @@ class Episode:
def __str__(self):
return f"Episode(id={self.id}, number={self.number}, name='{self.name}', plot='{self.plot}', duration={self.duration} sec)"
+
+ def to_dict(self) -> Dict[str, Any]:
+ return {
+ 'id': self.id,
+ 'number': self.number,
+ 'name': self.name,
+ 'plot': self.plot,
+ 'duration': self.duration,
+ 'scws_id': self.scws_id,
+ 'season_id': self.season_id,
+ 'created_by': self.created_by,
+ 'created_at': self.created_at,
+ 'updated_at': self.updated_at,
+ 'images': [image.to_dict() for image in self.images]
+ }
class EpisodeManager:
diff --git a/Src/Api/Streamingcommunity/Core/Class/PreviewType.py b/Src/Api/Streamingcommunity/Core/Class/PreviewType.py
index 28d741e..7b80b0a 100644
--- a/Src/Api/Streamingcommunity/Core/Class/PreviewType.py
+++ b/Src/Api/Streamingcommunity/Core/Class/PreviewType.py
@@ -60,4 +60,17 @@ class PreviewManager:
images_str = "\n".join(str(image) for image in self.images)
return f"Title: ID={self.id}, Type={self.type}, Runtime={self.runtime}, Release Date={self.release_date}, Quality={self.quality}, Plot={self.plot}, Seasons Count={self.seasons_count}\nGenres:\n{genres_str}\nPreview:\n{self.preview}\nImages:\n{images_str}"
+ def to_dict(self):
+ return {
+ "id": self.id,
+ "type": self.type,
+ "runtime": self.runtime,
+ "release_date": self.release_date,
+ "quality": self.quality,
+ "plot": self.plot,
+ "seasons_count": self.seasons_count,
+ "genres": [genre.__dict__ for genre in self.genres],
+ "preview": self.preview.__dict__,
+ "images": [image.__dict__ for image in self.images]
+ }
diff --git a/Src/Api/Streamingcommunity/Core/Class/SearchType.py b/Src/Api/Streamingcommunity/Core/Class/SearchType.py
index 115677d..4e20c1c 100644
--- a/Src/Api/Streamingcommunity/Core/Class/SearchType.py
+++ b/Src/Api/Streamingcommunity/Core/Class/SearchType.py
@@ -37,10 +37,44 @@ class MediaItem:
self.last_air_date: str = data.get('last_air_date')
self.seasons_count: int = data.get('seasons_count')
self.images: List[Image] = [Image(image_data) for image_data in data.get('images', [])]
+ self.comment: str = data.get('comment')
+ self.plot: str = data.get('plot')
def __str__(self):
return f"MediaItem(id={self.id}, slug='{self.slug}', name='{self.name}', type='{self.type}', score='{self.score}', sub_ita={self.sub_ita}, last_air_date='{self.last_air_date}', seasons_count={self.seasons_count}, images={self.images})"
+ @property
+ def to_dict(self) -> dict:
+ """
+ Convert the MediaItem to a dictionary.
+
+ Returns:
+ dict: The MediaItem as a dictionary.
+ """
+ return {
+ "id": self.id,
+ "slug": self.slug,
+ "name": self.name,
+ "type": self.type.upper(),
+ "score": self.score,
+ "sub_ita": self.sub_ita,
+ "last_air_date": self.last_air_date,
+ "seasons_count": self.seasons_count,
+ "images": [image.__dict__ for image in self.images],
+ "comment": self.comment,
+ "plot": self.plot
+ }
+
+ @property
+ def get_site_id(self) -> str:
+ """
+ Get the site ID of the media item.
+
+ Returns:
+ int: The site ID of the media item.
+ """
+ return f"{self.id}-{self.slug}"
+
class MediaManager:
def __init__(self):
diff --git a/api/__init__.py b/api/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/api/api/__init__.py b/api/api/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/api/api/asgi.py b/api/api/asgi.py
new file mode 100644
index 0000000..57b0c31
--- /dev/null
+++ b/api/api/asgi.py
@@ -0,0 +1,16 @@
+"""
+ASGI config for api project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "api.settings")
+
+application = get_asgi_application()
diff --git a/api/api/settings.py b/api/api/settings.py
new file mode 100644
index 0000000..d64cd0f
--- /dev/null
+++ b/api/api/settings.py
@@ -0,0 +1,140 @@
+"""
+Django settings for api project.
+
+Generated by 'django-admin startproject' using Django 4.2.7.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/4.2/ref/settings/
+"""
+
+from pathlib import Path
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = "django-insecure-7u!h-#6b--%h8()19so$s+t9cjh5y1+ljnqum*@gm))0(a_qka"
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+ "django.contrib.admin",
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ "django.contrib.sessions",
+ "django.contrib.messages",
+ "django.contrib.staticfiles",
+ "corsheaders",
+ "endpoints",
+ "rest_framework",
+]
+
+MIDDLEWARE = [
+ "corsheaders.middleware.CorsMiddleware",
+ "django.middleware.security.SecurityMiddleware",
+ "django.contrib.sessions.middleware.SessionMiddleware",
+ "django.middleware.common.CommonMiddleware",
+ "django.middleware.csrf.CsrfViewMiddleware",
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
+ "django.contrib.messages.middleware.MessageMiddleware",
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
+]
+
+ROOT_URLCONF = "api.urls"
+
+TEMPLATES = [
+ {
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ "DIRS": [],
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.debug",
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ ],
+ },
+ },
+]
+
+WSGI_APPLICATION = "api.wsgi.application"
+
+
+# Database
+# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
+
+DATABASES = {
+ "default": {
+ "ENGINE": "django.db.backends.sqlite3",
+ "NAME": BASE_DIR / "db.sqlite3",
+ }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+ {
+ "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
+ },
+ {
+ "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
+ },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/4.2/topics/i18n/
+
+LANGUAGE_CODE = "en-us"
+
+TIME_ZONE = "UTC"
+
+USE_I18N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/4.2/howto/static-files/
+
+STATIC_URL = "static/"
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
+
+CORS_ALLOWED_ORIGINS = [
+ "http://localhost:5173",
+]
+
+CORS_ALLOWED_METHODS = (
+ "DELETE",
+ "GET",
+ "OPTIONS",
+ "PATCH",
+ "POST",
+ "PUT",
+)
diff --git a/api/api/urls.py b/api/api/urls.py
new file mode 100644
index 0000000..30b52fe
--- /dev/null
+++ b/api/api/urls.py
@@ -0,0 +1,24 @@
+"""
+URL configuration for api project.
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+ https://docs.djangoproject.com/en/4.2/topics/http/urls/
+Examples:
+Function views
+ 1. Add an import: from my_app import views
+ 2. Add a URL to urlpatterns: path('', views.home, name='home')
+Class-based views
+ 1. Add an import: from other_app.views import Home
+ 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
+Including another URLconf
+ 1. Import the include() function: from django.urls import include, path
+ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
+"""
+
+from django.contrib import admin
+from django.urls import path, include
+
+urlpatterns = [
+ path("admin/", admin.site.urls),
+ path("api/", include("endpoints.urls")),
+]
diff --git a/api/api/wsgi.py b/api/api/wsgi.py
new file mode 100644
index 0000000..bfbc45a
--- /dev/null
+++ b/api/api/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for api project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "api.settings")
+
+application = get_wsgi_application()
diff --git a/api/endpoints/__init__.py b/api/endpoints/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/api/endpoints/admin.py b/api/endpoints/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/api/endpoints/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/api/endpoints/apps.py b/api/endpoints/apps.py
new file mode 100644
index 0000000..0cf6cd7
--- /dev/null
+++ b/api/endpoints/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class EndpointsConfig(AppConfig):
+ default_auto_field = "django.db.models.BigAutoField"
+ name = "endpoints"
diff --git a/api/endpoints/migrations/__init__.py b/api/endpoints/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/api/endpoints/models.py b/api/endpoints/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/api/endpoints/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/api/endpoints/tests.py b/api/endpoints/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/api/endpoints/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/api/endpoints/urls.py b/api/endpoints/urls.py
new file mode 100644
index 0000000..184bb2f
--- /dev/null
+++ b/api/endpoints/urls.py
@@ -0,0 +1,10 @@
+from rest_framework import routers
+
+from .views import SearchView#, DownloadView
+
+router = routers.DefaultRouter()
+
+router.register(r"search", SearchView, basename="search")
+#router.register(r"download", DownloadView, basename="download")
+
+urlpatterns = router.urls
diff --git a/api/endpoints/views.py b/api/endpoints/views.py
new file mode 100644
index 0000000..0df7062
--- /dev/null
+++ b/api/endpoints/views.py
@@ -0,0 +1,241 @@
+import json
+import os
+
+from django.http import StreamingHttpResponse
+
+from rest_framework import viewsets
+from rest_framework.decorators import action
+from rest_framework.response import Response
+
+from Src.Api.Animeunity import title_search as anime_search
+from Src.Api.Animeunity.Core.Vix_player.player import VideoSource as anime_source
+from Src.Api.Animeunity.site import media_search_manager as anime_media_manager
+
+from Src.Api.Streamingcommunity import title_search as sc_search, get_version_and_domain
+from Src.Api.Streamingcommunity.Core.Vix_player.player import VideoSource as film_video_source
+from Src.Api.Streamingcommunity.site import media_search_manager as film_media_manager
+
+
+class SearchView(viewsets.ViewSet):
+
+ def list(self, request):
+ self.search_query = request.query_params.get("search_terms")
+ self.type_search = request.query_params.get("type")
+
+ media_manager = anime_media_manager if self.type_search == "anime" else film_media_manager
+ media_manager.media_list = []
+ self.len_database = 0
+ if self.type_search == "film":
+ _, self.domain = get_version_and_domain()
+ self.len_database = sc_search(self.search_query, self.domain)
+ elif self.type_search == "anime":
+ self.len_database = anime_search(self.search_query)
+
+ media_list = media_manager.media_list
+
+ if self.len_database != 0:
+ data_to_return = []
+ for _, media in enumerate(media_list):
+ if self.type_search == "anime":
+ if media.type == "TV":
+ media.type = "TV_ANIME"
+ if media.type == "Movie":
+ media.type = "OVA"
+ data_to_return.append(media.to_dict)
+
+ return Response({"media": data_to_return})
+
+ return Response({"error": "No media found with that search query"})
+
+ @action(detail=False, methods=["get"])
+ def get_episodes_info(self, request):
+ self.media_id = request.query_params.get("media_id")
+ self.media_slug = request.query_params.get("media_slug")
+ self.type_media = request.query_params.get("type_media")
+
+ try:
+ match self.type_media:
+ case "TV":
+
+ def stream_episodes():
+ self.version, self.domain = get_version_and_domain()
+
+ video_source = film_video_source()
+ video_source.setup(
+ version=self.version,
+ domain=self.domain,
+ media_id=self.media_id,
+ series_name=self.media_slug
+ )
+ video_source.collect_info_seasons()
+ seasons_count = video_source.obj_title_manager.get_length()
+
+ episodes = {}
+ for i_season in range(1, seasons_count + 1):
+ video_source.obj_episode_manager.clear()
+ video_source.collect_title_season(i_season)
+ episodes_count = (
+ video_source.obj_episode_manager.get_length()
+ )
+ episodes[i_season] = {}
+ for i_episode in range(1, episodes_count + 1):
+ episode = video_source.obj_episode_manager.episodes[
+ i_episode - 1
+ ]
+ episodes[i_season][i_episode] = episode.to_dict()
+
+ yield f'{json.dumps({"episodes": episodes})}\n\n'
+
+ response = StreamingHttpResponse(
+ stream_episodes(), content_type="text/event-stream"
+ )
+ return response
+
+ case "TV_ANIME":
+ def stream_episodes():
+ video_source = anime_source()
+ video_source.setup(
+ media_id = self.media_id,
+ series_name = self.media_slug
+ )
+ episoded_count = video_source.get_count_episodes()
+
+ for i in range(0, episoded_count):
+ episode_info = video_source.get_info_episode(i).to_dict()
+ episode_info["episode_id"] = i
+ episode_info["episode_total"] = episoded_count
+ print(f"Getting episode {i} of {episoded_count} info...")
+ yield f"{json.dumps(episode_info)}\n\n"
+
+ response = StreamingHttpResponse(
+ stream_episodes(), content_type="text/event-stream"
+ )
+ return response
+
+ except Exception as e:
+ return Response(
+ {
+ "error": "Error while getting episodes info",
+ "message": str(e),
+ }
+ )
+
+ return Response({"error": "No media found with that search query"})
+
+ @action(detail=False, methods=["get"])
+ def get_preview(self, request):
+ self.media_id = request.query_params.get("media_id")
+ self.media_slug = request.query_params.get("media_slug")
+ self.type_media = request.query_params.get("type_media")
+
+ try:
+ if self.type_media in ["TV", "MOVIE"]:
+ version, domain = get_version_and_domain()
+ video_source = film_video_source()
+ video_source.setup(media_id=self.media_id, version=version, domain=domain, series_name=self.media_slug)
+ video_source.get_preview()
+ return Response(video_source.obj_preview.to_dict())
+ if self.type_media in ["TV_ANIME", "OVA", "SPECIAL"]:
+ video_source = anime_source()
+ video_source.setup(media_id=self.media_id, series_name=self.media_slug)
+ video_source.get_preview()
+ return Response(video_source.obj_preview.to_dict())
+ except Exception as e:
+ return Response(
+ {
+ "error": "Error while getting preview info",
+ "message": str(e),
+ }
+ )
+
+ return Response({"error": "No media found with that search query"})
+
+
+'''
+class DownloadView(viewsets.ViewSet):
+
+ def create(self, request):
+ self.media_id = request.data.get("media_id")
+ self.media_slug = request.data.get("media_slug")
+ self.type_media = request.data.get("type_media").upper()
+ self.download_id = request.data.get("download_id")
+ self.tv_series_episode_id = request.data.get("tv_series_episode_id")
+
+ if self.type_media in ["TV", "MOVIE"]:
+ self.site_version, self.domain = get_version_and_domain()
+
+ response_dict = {"error": "No media found with that search query"}
+
+ try:
+ match self.type_media:
+ case "MOVIE":
+ download_film(self.media_id, self.media_slug, self.domain)
+ case "TV":
+ video_source = VideoSource()
+ video_source.set_url_base_name(STREAM_SITE_NAME)
+ video_source.set_version(self.site_version)
+ video_source.set_domain(self.domain)
+ video_source.set_series_name(self.media_slug)
+ video_source.set_media_id(self.media_id)
+
+ video_source.collect_info_seasons()
+ video_source.obj_episode_manager.clear()
+
+ video_source.collect_title_season(self.download_id)
+ episodes_count = video_source.obj_episode_manager.get_length()
+ for i_episode in range(1, episodes_count + 1):
+ episode_id = video_source.obj_episode_manager.episodes[
+ i_episode - 1
+ ].id
+
+ # Define filename and path for the downloaded video
+ mp4_name = remove_special_characters(
+ f"{map_episode_title(self.media_slug,video_source.obj_episode_manager.episodes[i_episode - 1],self.download_id)}.mp4"
+ )
+ mp4_path = remove_special_characters(
+ os.path.join(
+ ROOT_PATH,
+ SERIES_FOLDER,
+ self.media_slug,
+ f"S{self.download_id}",
+ )
+ )
+ os.makedirs(mp4_path, exist_ok=True)
+
+ # Get iframe and content for the episode
+ video_source.get_iframe(episode_id)
+ video_source.get_content()
+ video_source.set_url_base_name(STREAM_SITE_NAME)
+
+ # Download the episode
+ obj_download = Downloader(
+ m3u8_playlist=video_source.get_playlist(),
+ key=video_source.get_key(),
+ output_filename=os.path.join(mp4_path, mp4_name),
+ )
+
+ obj_download.download_m3u8()
+
+ case "TV_ANIME":
+ episodes_downloader = EpisodeDownloader(
+ self.media_id, self.media_slug
+ )
+ episodes_downloader.download_episode(self.download_id)
+ case "OVA" | "SPECIAL":
+ anime_download_film(
+ id_film=self.media_id, title_name=self.media_slug
+ )
+ case _:
+ raise Exception("Type media not supported")
+
+ response_dict = {
+ "message": "Download done, it is saved in Video folder inside project root"
+ }
+ except Exception as e:
+ response_dict = {
+ "error": "Error while downloading the media",
+ "message": str(e),
+ }
+
+ return Response(response_dict)
+'''
diff --git a/api/manage.py b/api/manage.py
new file mode 100755
index 0000000..3b72e09
--- /dev/null
+++ b/api/manage.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
+
+
+def main():
+ """Run administrative tasks."""
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "api.settings")
+ try:
+ from django.core.management import execute_from_command_line
+ except ImportError as exc:
+ raise ImportError(
+ "Couldn't import Django. Are you sure it's installed and "
+ "available on your PYTHONPATH environment variable? Did you "
+ "forget to activate a virtual environment?"
+ ) from exc
+ execute_from_command_line(sys.argv)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/config.json b/config.json
index 2603713..c2bc0e2 100644
--- a/config.json
+++ b/config.json
@@ -45,4 +45,4 @@
"animeunity": "to",
"altadefinizione": "food"
}
-}
+}
\ No newline at end of file
diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs
new file mode 100644
index 0000000..6f40582
--- /dev/null
+++ b/frontend/.eslintrc.cjs
@@ -0,0 +1,15 @@
+/* eslint-env node */
+require('@rushstack/eslint-patch/modern-module-resolution')
+
+module.exports = {
+ root: true,
+ 'extends': [
+ 'plugin:vue/vue3-essential',
+ 'eslint:recommended',
+ '@vue/eslint-config-typescript',
+ '@vue/eslint-config-prettier/skip-formatting'
+ ],
+ parserOptions: {
+ ecmaVersion: 'latest'
+ }
+}
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000..8ee54e8
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,30 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+.DS_Store
+dist
+dist-ssr
+coverage
+*.local
+
+/cypress/videos/
+/cypress/screenshots/
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+*.tsbuildinfo
diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json
new file mode 100644
index 0000000..66e2335
--- /dev/null
+++ b/frontend/.prettierrc.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/prettierrc",
+ "semi": false,
+ "tabWidth": 2,
+ "singleQuote": true,
+ "printWidth": 100,
+ "trailingComma": "none"
+}
\ No newline at end of file
diff --git a/frontend/.vscode/extensions.json b/frontend/.vscode/extensions.json
new file mode 100644
index 0000000..93ea3e7
--- /dev/null
+++ b/frontend/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ "recommendations": [
+ "Vue.volar",
+ "dbaeumer.vscode-eslint",
+ "esbenp.prettier-vscode"
+ ]
+}
diff --git a/frontend/README.md b/frontend/README.md
new file mode 100644
index 0000000..9b4c74c
--- /dev/null
+++ b/frontend/README.md
@@ -0,0 +1,39 @@
+# frontend
+
+This template should help get you started developing with Vue 3 in Vite.
+
+## Recommended IDE Setup
+
+[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
+
+## Type Support for `.vue` Imports in TS
+
+TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
+
+## Customize configuration
+
+See [Vite Configuration Reference](https://vitejs.dev/config/).
+
+## Project Setup
+
+```sh
+npm install
+```
+
+### Compile and Hot-Reload for Development
+
+```sh
+npm run dev
+```
+
+### Type-Check, Compile and Minify for Production
+
+```sh
+npm run build
+```
+
+### Lint with [ESLint](https://eslint.org/)
+
+```sh
+npm run lint
+```
diff --git a/frontend/env.d.ts b/frontend/env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/frontend/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..a888544
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite App
+
+
+
+
+
+
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
new file mode 100644
index 0000000..dd00361
--- /dev/null
+++ b/frontend/package-lock.json
@@ -0,0 +1,3225 @@
+{
+ "name": "frontend",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "frontend",
+ "version": "0.0.0",
+ "dependencies": {
+ "axios": "^1.6.8",
+ "vue": "^3.4.21",
+ "vue-router": "^4.3.0"
+ },
+ "devDependencies": {
+ "@rushstack/eslint-patch": "^1.8.0",
+ "@tsconfig/node20": "^20.1.4",
+ "@types/node": "^20.12.5",
+ "@vitejs/plugin-vue": "^5.0.4",
+ "@vue/eslint-config-prettier": "^9.0.0",
+ "@vue/eslint-config-typescript": "^13.0.0",
+ "@vue/tsconfig": "^0.5.1",
+ "eslint": "^8.57.0",
+ "eslint-plugin-vue": "^9.23.0",
+ "npm-run-all2": "^6.1.2",
+ "prettier": "^3.2.5",
+ "typescript": "~5.4.0",
+ "vite": "^5.2.8",
+ "vue-tsc": "^2.0.11"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.24.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz",
+ "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
+ "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
+ "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
+ "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
+ "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
+ "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
+ "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
+ "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
+ "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
+ "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
+ "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
+ "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
+ "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
+ "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
+ "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
+ "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
+ "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
+ "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
+ "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
+ "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
+ "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
+ "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
+ "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
+ "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgr/core": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.0.tgz",
+ "integrity": "sha512-nNvLvC2fjC+3+bHYN9uaGF3gcyy7RHGZhtl8TB/kINj9hiOQza8kWJGZh47GRPMrqeseO8U+Z8ElDMCZlWBdHA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.0.tgz",
+ "integrity": "sha512-+kjt6dvxnyTIAo7oHeYseYhDyZ7xRKTNl/FoQI96PHkJVxoChldJnne/LzYqpqidoK1/0kX0/q+5rrYqjpth6w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.0.tgz",
+ "integrity": "sha512-Oj6Tp0unMpGTBjvNwbSRv3DopMNLu+mjBzhKTt2zLbDJ/45fB1pltr/rqrO4bE95LzuYwhYn127pop+x/pzf5w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.0.tgz",
+ "integrity": "sha512-3nJx0T+yptxMd+v93rBRxSPTAVCv8szu/fGZDJiKX7kvRe9sENj2ggXjCH/KK1xZEmJOhaNo0c9sGMgGdfkvEw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.0.tgz",
+ "integrity": "sha512-Vb2e8p9b2lxxgqyOlBHmp6hJMu/HSU6g//6Tbr7x5V1DlPCHWLOm37nSIVK314f+IHzORyAQSqL7+9tELxX3zQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.0.tgz",
+ "integrity": "sha512-Md60KsmC5ZIaRq/bYYDloklgU+XLEZwS2EXXVcSpiUw+13/ZASvSWQ/P92rQ9YDCL6EIoXxuQ829JkReqdYbGg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.0.tgz",
+ "integrity": "sha512-zL5rBFtJ+2EGnMRm2TqKjdjgFqlotSU+ZJEN37nV+fiD3I6Gy0dUh3jBWN0wSlcXVDEJYW7YBe+/2j0N9unb2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.0.tgz",
+ "integrity": "sha512-s2xAyNkJqUdtRVgNK4NK4P9QttS538JuX/kfVQOdZDI5FIKVAUVdLW7qhGfmaySJ1EvN/Bnj9oPm5go9u8navg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.0.tgz",
+ "integrity": "sha512-7F99yzVT67B7IUNMjLD9QCFDCyHkyCJMS1dywZrGgVFJao4VJ9szrIEgH67cR+bXQgEaY01ur/WSL6B0jtcLyA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.0.tgz",
+ "integrity": "sha512-leFtyiXisfa3Sg9pgZJwRKITWnrQfhtqDjCamnZhkZuIsk1FXmYwKoTkp6lsCgimIcneFFkHKp/yGLxDesga4g==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.0.tgz",
+ "integrity": "sha512-FtOgui6qMJ4jbSXTxElsy/60LEe/3U0rXkkz2G5CJ9rbHPAvjMvI+3qF0A0fwLQ5hW+/ZC6PbnS2KfRW9JkgDQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.0.tgz",
+ "integrity": "sha512-v6eiam/1w3HUfU/ZjzIDodencqgrSqzlNuNtiwH7PFJHYSo1ezL0/UIzmS2lpSJF1ORNaplXeKHYmmdt81vV2g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.0.tgz",
+ "integrity": "sha512-OUhkSdpM5ofVlVU2k4CwVubYwiwu1a4jYWPpubzN7Vzao73GoPBowHcCfaRSFRz1SszJ3HIsk3dZYk4kzbqjgw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.0.tgz",
+ "integrity": "sha512-uL7UYO/MNJPGL/yflybI+HI+n6+4vlfZmQZOCb4I+z/zy1wisHT3exh7oNQsnL6Eso0EUTEfgQ/PaGzzXf6XyQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.0.tgz",
+ "integrity": "sha512-4WnSgaUiUmXILwFqREdOcqvSj6GD/7FrvSjhaDjmwakX9w4Z2F8JwiSP1AZZbuRkPqzi444UI5FPv33VKOWYFQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.0.tgz",
+ "integrity": "sha512-ve+D8t1prRSRnF2S3pyDtTXDlvW1Pngbz76tjgYFQW1jxVSysmQCZfPoDAo4WP+Ano8zeYp85LsArZBI12HfwQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz",
+ "integrity": "sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==",
+ "dev": true
+ },
+ "node_modules/@tsconfig/node20": {
+ "version": "20.1.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.4.tgz",
+ "integrity": "sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==",
+ "dev": true
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+ "dev": true
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.12.7",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz",
+ "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==",
+ "dev": true,
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.8",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
+ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz",
+ "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "7.7.1",
+ "@typescript-eslint/type-utils": "7.7.1",
+ "@typescript-eslint/utils": "7.7.1",
+ "@typescript-eslint/visitor-keys": "7.7.1",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.3.1",
+ "natural-compare": "^1.4.0",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^7.0.0",
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz",
+ "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "7.7.1",
+ "@typescript-eslint/types": "7.7.1",
+ "@typescript-eslint/typescript-estree": "7.7.1",
+ "@typescript-eslint/visitor-keys": "7.7.1",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz",
+ "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.7.1",
+ "@typescript-eslint/visitor-keys": "7.7.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz",
+ "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "7.7.1",
+ "@typescript-eslint/utils": "7.7.1",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz",
+ "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz",
+ "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.7.1",
+ "@typescript-eslint/visitor-keys": "7.7.1",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz",
+ "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.15",
+ "@types/semver": "^7.5.8",
+ "@typescript-eslint/scope-manager": "7.7.1",
+ "@typescript-eslint/types": "7.7.1",
+ "@typescript-eslint/typescript-estree": "7.7.1",
+ "semver": "^7.6.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz",
+ "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.7.1",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
+ "node_modules/@vitejs/plugin-vue": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
+ "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==",
+ "dev": true,
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^5.0.0",
+ "vue": "^3.2.25"
+ }
+ },
+ "node_modules/@volar/language-core": {
+ "version": "2.2.0-alpha.10",
+ "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.2.0-alpha.10.tgz",
+ "integrity": "sha512-njVJLtpu0zMvDaEk7K5q4BRpOgbyEUljU++un9TfJoJNhxG0z/hWwpwgTRImO42EKvwIxF3XUzeMk+qatAFy7Q==",
+ "dev": true,
+ "dependencies": {
+ "@volar/source-map": "2.2.0-alpha.10"
+ }
+ },
+ "node_modules/@volar/source-map": {
+ "version": "2.2.0-alpha.10",
+ "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.2.0-alpha.10.tgz",
+ "integrity": "sha512-nrdWApVkP5cksAnDEyy1JD9rKdwOJsEq1B+seWO4vNXmZNcxQQCx4DULLBvKt7AzRUAQiAuw5aQkb9RBaSqdVA==",
+ "dev": true,
+ "dependencies": {
+ "muggle-string": "^0.4.0"
+ }
+ },
+ "node_modules/@volar/typescript": {
+ "version": "2.2.0-alpha.10",
+ "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.2.0-alpha.10.tgz",
+ "integrity": "sha512-GCa0vTVVdA9ULUsu2Rx7jwsIuyZQPvPVT9o3NrANTbYv+523Ao1gv3glC5vzNSDPM6bUl37r94HbCj7KINQr+g==",
+ "dev": true,
+ "dependencies": {
+ "@volar/language-core": "2.2.0-alpha.10",
+ "path-browserify": "^1.0.1"
+ }
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.25.tgz",
+ "integrity": "sha512-Y2pLLopaElgWnMNolgG8w3C5nNUVev80L7hdQ5iIKPtMJvhVpG0zhnBG/g3UajJmZdvW0fktyZTotEHD1Srhbg==",
+ "dependencies": {
+ "@babel/parser": "^7.24.4",
+ "@vue/shared": "3.4.25",
+ "entities": "^4.5.0",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.0"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.25.tgz",
+ "integrity": "sha512-Ugz5DusW57+HjllAugLci19NsDK+VyjGvmbB2TXaTcSlQxwL++2PETHx/+Qv6qFwNLzSt7HKepPe4DcTE3pBWg==",
+ "dependencies": {
+ "@vue/compiler-core": "3.4.25",
+ "@vue/shared": "3.4.25"
+ }
+ },
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.25.tgz",
+ "integrity": "sha512-m7rryuqzIoQpOBZ18wKyq05IwL6qEpZxFZfRxlNYuIPDqywrXQxgUwLXIvoU72gs6cRdY6wHD0WVZIFE4OEaAQ==",
+ "dependencies": {
+ "@babel/parser": "^7.24.4",
+ "@vue/compiler-core": "3.4.25",
+ "@vue/compiler-dom": "3.4.25",
+ "@vue/compiler-ssr": "3.4.25",
+ "@vue/shared": "3.4.25",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.10",
+ "postcss": "^8.4.38",
+ "source-map-js": "^1.2.0"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.25.tgz",
+ "integrity": "sha512-H2ohvM/Pf6LelGxDBnfbbXFPyM4NE3hrw0e/EpwuSiYu8c819wx+SVGdJ65p/sFrYDd6OnSDxN1MB2mN07hRSQ==",
+ "dependencies": {
+ "@vue/compiler-dom": "3.4.25",
+ "@vue/shared": "3.4.25"
+ }
+ },
+ "node_modules/@vue/devtools-api": {
+ "version": "6.6.1",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz",
+ "integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA=="
+ },
+ "node_modules/@vue/eslint-config-prettier": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
+ "integrity": "sha512-z1ZIAAUS9pKzo/ANEfd2sO+v2IUalz7cM/cTLOZ7vRFOPk5/xuRKQteOu1DErFLAh/lYGXMVZ0IfYKlyInuDVg==",
+ "dev": true,
+ "dependencies": {
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-plugin-prettier": "^5.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">= 8.0.0",
+ "prettier": ">= 3.0.0"
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-13.0.0.tgz",
+ "integrity": "sha512-MHh9SncG/sfqjVqjcuFLOLD6Ed4dRAis4HNt0dXASeAuLqIAx4YMB1/m2o4pUKK1vCt8fUvYG8KKX2Ot3BVZTg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "^7.1.1",
+ "@typescript-eslint/parser": "^7.1.1",
+ "vue-eslint-parser": "^9.3.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0",
+ "eslint-plugin-vue": "^9.0.0",
+ "typescript": ">=4.7.4"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/language-core": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.14.tgz",
+ "integrity": "sha512-3q8mHSNcGTR7sfp2X6jZdcb4yt8AjBXAfKk0qkZIh7GAJxOnoZ10h5HToZglw4ToFvAnq+xu/Z2FFbglh9Icag==",
+ "dev": true,
+ "dependencies": {
+ "@volar/language-core": "2.2.0-alpha.10",
+ "@vue/compiler-dom": "^3.4.0",
+ "@vue/shared": "^3.4.0",
+ "computeds": "^0.0.1",
+ "minimatch": "^9.0.3",
+ "path-browserify": "^1.0.1",
+ "vue-template-compiler": "^2.7.14"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.25.tgz",
+ "integrity": "sha512-mKbEtKr1iTxZkAG3vm3BtKHAOhuI4zzsVcN0epDldU/THsrvfXRKzq+lZnjczZGnTdh3ojd86/WrP+u9M51pWQ==",
+ "dependencies": {
+ "@vue/shared": "3.4.25"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.25.tgz",
+ "integrity": "sha512-3qhsTqbEh8BMH3pXf009epCI5E7bKu28fJLi9O6W+ZGt/6xgSfMuGPqa5HRbUxLoehTNp5uWvzCr60KuiRIL0Q==",
+ "dependencies": {
+ "@vue/reactivity": "3.4.25",
+ "@vue/shared": "3.4.25"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.25.tgz",
+ "integrity": "sha512-ode0sj77kuwXwSc+2Yhk8JMHZh1sZp9F/51wdBiz3KGaWltbKtdihlJFhQG4H6AY+A06zzeMLkq6qu8uDSsaoA==",
+ "dependencies": {
+ "@vue/runtime-core": "3.4.25",
+ "@vue/shared": "3.4.25",
+ "csstype": "^3.1.3"
+ }
+ },
+ "node_modules/@vue/server-renderer": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.25.tgz",
+ "integrity": "sha512-8VTwq0Zcu3K4dWV0jOwIVINESE/gha3ifYCOKEhxOj6MEl5K5y8J8clQncTcDhKF+9U765nRw4UdUEXvrGhyVQ==",
+ "dependencies": {
+ "@vue/compiler-ssr": "3.4.25",
+ "@vue/shared": "3.4.25"
+ },
+ "peerDependencies": {
+ "vue": "3.4.25"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.25.tgz",
+ "integrity": "sha512-k0yappJ77g2+KNrIaF0FFnzwLvUBLUYr8VOwz+/6vLsmItFp51AcxLL7Ey3iPd7BIRyWPOcqUjMnm7OkahXllA=="
+ },
+ "node_modules/@vue/tsconfig": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz",
+ "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==",
+ "dev": true
+ },
+ "node_modules/acorn": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/axios": {
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
+ "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/computeds": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz",
+ "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+ },
+ "node_modules/de-indent": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
+ "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
+ "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.20.2",
+ "@esbuild/android-arm": "0.20.2",
+ "@esbuild/android-arm64": "0.20.2",
+ "@esbuild/android-x64": "0.20.2",
+ "@esbuild/darwin-arm64": "0.20.2",
+ "@esbuild/darwin-x64": "0.20.2",
+ "@esbuild/freebsd-arm64": "0.20.2",
+ "@esbuild/freebsd-x64": "0.20.2",
+ "@esbuild/linux-arm": "0.20.2",
+ "@esbuild/linux-arm64": "0.20.2",
+ "@esbuild/linux-ia32": "0.20.2",
+ "@esbuild/linux-loong64": "0.20.2",
+ "@esbuild/linux-mips64el": "0.20.2",
+ "@esbuild/linux-ppc64": "0.20.2",
+ "@esbuild/linux-riscv64": "0.20.2",
+ "@esbuild/linux-s390x": "0.20.2",
+ "@esbuild/linux-x64": "0.20.2",
+ "@esbuild/netbsd-x64": "0.20.2",
+ "@esbuild/openbsd-x64": "0.20.2",
+ "@esbuild/sunos-x64": "0.20.2",
+ "@esbuild/win32-arm64": "0.20.2",
+ "@esbuild/win32-ia32": "0.20.2",
+ "@esbuild/win32-x64": "0.20.2"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
+ "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.6"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": "*",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-vue": {
+ "version": "9.25.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.25.0.tgz",
+ "integrity": "sha512-tDWlx14bVe6Bs+Nnh3IGrD+hb11kf2nukfm6jLsmJIhmiRQ1SUaksvwY9U5MvPB0pcrg0QK0xapQkfITs3RKOA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "globals": "^13.24.0",
+ "natural-compare": "^1.4.0",
+ "nth-check": "^2.1.1",
+ "postcss-selector-parser": "^6.0.15",
+ "semver": "^7.6.0",
+ "vue-eslint-parser": "^9.4.2",
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz",
+ "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.10",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
+ "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ }
+ },
+ "node_modules/memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+ "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/muggle-string": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
+ "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
+ "dev": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/npm-normalize-package-bin": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz",
+ "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-run-all2": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-6.1.2.tgz",
+ "integrity": "sha512-WwwnS8Ft+RpXve6T2EIEVpFLSqN+ORHRvgNk3H9N62SZXjmzKoRhMFg3I17TK3oMaAEr+XFbRirWS2Fn3BCPSg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "cross-spawn": "^7.0.3",
+ "memorystream": "^0.3.1",
+ "minimatch": "^9.0.0",
+ "pidtree": "^0.6.0",
+ "read-package-json-fast": "^3.0.2",
+ "shell-quote": "^1.7.3"
+ },
+ "bin": {
+ "npm-run-all": "bin/npm-run-all/index.js",
+ "npm-run-all2": "bin/npm-run-all/index.js",
+ "run-p": "bin/run-p/index.js",
+ "run-s": "bin/run-s/index.js"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0",
+ "npm": ">= 8"
+ }
+ },
+ "node_modules/npm-run-all2/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-browserify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+ "dev": true
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pidtree": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
+ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+ "dev": true,
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.16",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
+ "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
+ "dev": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
+ "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/read-package-json-fast": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz",
+ "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==",
+ "dev": true,
+ "dependencies": {
+ "json-parse-even-better-errors": "^3.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.0.tgz",
+ "integrity": "sha512-wZJSn0WMtWrxhYKQRt5Z6GIXlziOoMDFmbHmRfL3v+sBTAshx2DBq1AfMArB7eIjF63r4ocn2ZTAyUptg/7kmQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "1.0.5"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.17.0",
+ "@rollup/rollup-android-arm64": "4.17.0",
+ "@rollup/rollup-darwin-arm64": "4.17.0",
+ "@rollup/rollup-darwin-x64": "4.17.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.17.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.17.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.17.0",
+ "@rollup/rollup-linux-arm64-musl": "4.17.0",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.17.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.17.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.17.0",
+ "@rollup/rollup-linux-x64-gnu": "4.17.0",
+ "@rollup/rollup-linux-x64-musl": "4.17.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.17.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.17.0",
+ "@rollup/rollup-win32-x64-msvc": "4.17.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+ "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+ "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/synckit": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
+ "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/core": "^0.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-api-utils": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
+ "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.4.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
+ "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
+ "devOptional": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/vite": {
+ "version": "5.2.10",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz",
+ "integrity": "sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.20.1",
+ "postcss": "^8.4.38",
+ "rollup": "^4.13.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue": {
+ "version": "3.4.25",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.25.tgz",
+ "integrity": "sha512-HWyDqoBHMgav/OKiYA2ZQg+kjfMgLt/T0vg4cbIF7JbXAjDexRf5JRg+PWAfrAkSmTd2I8aPSXtooBFWHB98cg==",
+ "dependencies": {
+ "@vue/compiler-dom": "3.4.25",
+ "@vue/compiler-sfc": "3.4.25",
+ "@vue/runtime-dom": "3.4.25",
+ "@vue/server-renderer": "3.4.25",
+ "@vue/shared": "3.4.25"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue-eslint-parser": {
+ "version": "9.4.2",
+ "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz",
+ "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4",
+ "eslint-scope": "^7.1.1",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.3.1",
+ "esquery": "^1.4.0",
+ "lodash": "^4.17.21",
+ "semver": "^7.3.6"
+ },
+ "engines": {
+ "node": "^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=6.0.0"
+ }
+ },
+ "node_modules/vue-router": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.2.tgz",
+ "integrity": "sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==",
+ "dependencies": {
+ "@vue/devtools-api": "^6.5.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/posva"
+ },
+ "peerDependencies": {
+ "vue": "^3.2.0"
+ }
+ },
+ "node_modules/vue-template-compiler": {
+ "version": "2.7.16",
+ "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
+ "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==",
+ "dev": true,
+ "dependencies": {
+ "de-indent": "^1.0.2",
+ "he": "^1.2.0"
+ }
+ },
+ "node_modules/vue-tsc": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.14.tgz",
+ "integrity": "sha512-DgAO3U1cnCHOUO7yB35LENbkapeRsBZ7Ugq5hGz/QOHny0+1VQN8eSwSBjYbjLVPfvfw6EY7sNPjbuHHUhckcg==",
+ "dev": true,
+ "dependencies": {
+ "@volar/typescript": "2.2.0-alpha.10",
+ "@vue/language-core": "2.0.14",
+ "semver": "^7.5.4"
+ },
+ "bin": {
+ "vue-tsc": "bin/vue-tsc.js"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/xml-name-validator": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000..10a021d
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "frontend",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "run-p type-check \"build-only {@}\" --",
+ "preview": "vite preview",
+ "build-only": "vite build",
+ "type-check": "vue-tsc --build --force",
+ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
+ "format": "prettier --write src/"
+ },
+ "dependencies": {
+ "axios": "^1.6.8",
+ "vue": "^3.4.21",
+ "vue-router": "^4.3.0"
+ },
+ "devDependencies": {
+ "@rushstack/eslint-patch": "^1.8.0",
+ "@tsconfig/node20": "^20.1.4",
+ "@types/node": "^20.12.5",
+ "@vitejs/plugin-vue": "^5.0.4",
+ "@vue/eslint-config-prettier": "^9.0.0",
+ "@vue/eslint-config-typescript": "^13.0.0",
+ "@vue/tsconfig": "^0.5.1",
+ "eslint": "^8.57.0",
+ "eslint-plugin-vue": "^9.23.0",
+ "npm-run-all2": "^6.1.2",
+ "prettier": "^3.2.5",
+ "typescript": "~5.4.0",
+ "vite": "^5.2.8",
+ "vue-tsc": "^2.0.11"
+ }
+}
diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2
GIT binary patch
literal 4286
zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj
zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56
zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy
zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei
z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX
zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm
zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp=
zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8
zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO
z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3
z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD
zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6
z={Xwx{T%b6i9IjI)Ls)S{-*mq<@~R{?$}ZKjf;^k75i_}(2MXt}^SEBVg7AI@28
zo_uPg2V)_e-`2Ois=PYoe%9u*n9({PFR)OnHJPi{dNx>KxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S
literal 0
HcmV?d00001
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
new file mode 100644
index 0000000..ad56b70
--- /dev/null
+++ b/frontend/src/App.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/frontend/src/api/api.ts b/frontend/src/api/api.ts
new file mode 100644
index 0000000..7ec0039
--- /dev/null
+++ b/frontend/src/api/api.ts
@@ -0,0 +1,81 @@
+import axios from "axios";
+import type { AxiosResponse } from "axios";
+import type { DownloadResponse, MediaItemResponse } from "@/api/interfaces";
+
+const BASE_URL = "http://localhost:8000/api";
+
+const api = axios.create({
+ baseURL: BASE_URL,
+});
+
+async function get(url: string): Promise> {
+ return api.get(url);
+}
+
+async function post(url: string, data: any): Promise> {
+ return api.post(url, data);
+}
+
+export default function search(
+ query: string,
+ type: string
+): Promise> {
+ return get(`/search?search_terms=${query}&type=${type}`);
+}
+
+export async function getEpisodesInfo(
+ mediaId: number,
+ mediaSlug: string,
+ mediaType: string
+): Promise {
+ const url = `/search/get_episodes_info?media_id=${mediaId}&media_slug=${mediaSlug}&type_media=${mediaType}`;
+ return fetch(`${BASE_URL}${url}`, {
+ method: "GET",
+ headers: {
+ "Content-Type": "text/event-stream",
+ },
+ });
+}
+
+export async function getPreview(
+ mediaId: number,
+ mediaSlug: string,
+ mediaType: string
+): Promise> {
+ const url = `/search/get_preview?media_id=${mediaId}&media_slug=${mediaSlug}&type_media=${mediaType}`;
+ return get(url);
+}
+
+async function downloadMedia(
+ mediaId: number,
+ mediaSlug: string,
+ mediaType: string,
+ downloadId?: number,
+ tvSeriesEpisodeId?: number
+): Promise> {
+ const url = `/download/`;
+ const data = {
+ media_id: mediaId,
+ media_slug: mediaSlug,
+ type_media: mediaType,
+ download_id: downloadId,
+ tv_series_episode_id: tvSeriesEpisodeId,
+ };
+ return post(url, data);
+}
+
+export const downloadFilm = (mediaId: number, mediaSlug: string) =>
+ downloadMedia(mediaId, mediaSlug, "MOVIE");
+export const downloadTvSeries = (
+ mediaId: number,
+ mediaSlug: string,
+ downloadId: number,
+ tvSeriesEpisodeId?: number
+) => downloadMedia(mediaId, mediaSlug, "TV", downloadId, tvSeriesEpisodeId);
+export const downloadAnimeFilm = (mediaId: number, mediaSlug: string) =>
+ downloadMedia(mediaId, mediaSlug, "OVA");
+export const downloadAnimeSeries = (
+ mediaId: number,
+ mediaSlug: string,
+ downloadId: number
+) => downloadMedia(mediaId, mediaSlug, "TV_ANIME", downloadId);
diff --git a/frontend/src/api/interfaces.ts b/frontend/src/api/interfaces.ts
new file mode 100644
index 0000000..d33f703
--- /dev/null
+++ b/frontend/src/api/interfaces.ts
@@ -0,0 +1,64 @@
+interface Image {
+ imageable_id: number;
+ imageable_type: string;
+ filename: string;
+ type: string;
+ original_url_field: string;
+}
+
+export interface MediaItem {
+ id: number;
+ slug: string;
+ name: string;
+ type: string;
+ score: string;
+ sub_ita: number;
+ last_air_date: string;
+ seasons_count: number;
+ images: Image[];
+ comment: string;
+ plot: string;
+}
+
+export interface MediaItemResponse {
+ media: MediaItem[];
+}
+
+export interface Episode {
+ id: number;
+ anime_id: number;
+ user_id: number | null;
+ number: string;
+ created_at: string;
+ link: string;
+ visite: number;
+ hidden: number;
+ public: number;
+ scws_id: number;
+ file_name: string;
+ tg_post: number;
+ episode_id: number;
+ episode_total: number;
+ name: string; // TV Show exclusive
+ plot: string; // TV Show exclusive
+ duration: number; // TV Show exclusive
+ season_id: number; // TV Show exclusive
+ created_by: any; // TV Show exclusive
+ updated_at: string; // TV Show exclusive
+ season_index: number; // TV Show exclusive
+}
+
+export interface Season {
+ [key: string]: {
+ [key: string]: Episode;
+ };
+}
+
+export interface SeasonResponse {
+ episodes: Season;
+}
+
+export interface DownloadResponse {
+ error: string;
+ message: string;
+}
\ No newline at end of file
diff --git a/frontend/src/api/utils.ts b/frontend/src/api/utils.ts
new file mode 100644
index 0000000..4432fdd
--- /dev/null
+++ b/frontend/src/api/utils.ts
@@ -0,0 +1,63 @@
+import {downloadAnimeFilm, downloadAnimeSeries, downloadFilm, downloadTvSeries} from "@/api/api";
+import type {DownloadResponse, Episode, MediaItem, Season} from "@/api/interfaces";
+
+export const handleTVDownload = async (tvShowEpisodes: any[], item: MediaItem) => {
+ alertDownload();
+ for (const season of tvShowEpisodes) {
+ const i = tvShowEpisodes.indexOf(season);
+ const res = (await downloadTvSeries(item.id, item.slug, i + 1)).data;
+ handleDownloadError(res);
+ }
+};
+
+export const handleTVEpisodesDownload = async (episodes: Episode[], item: MediaItem) => {
+ alertDownload();
+ for (const episode of episodes) {
+ const i = episodes.indexOf(episode);
+ const res = (await downloadTvSeries(item.id, item.slug, episode.season_index + 1, i)).data;
+ handleDownloadError(res);
+ }
+}
+
+export const handleMovieDownload = async (item: MediaItem) => {
+ alertDownload();
+ const res = (await downloadFilm(item.id, item.slug)).data;
+ handleDownloadError(res);
+};
+
+export const handleTVAnimeDownload = async (episodeCount: number, item: MediaItem) => {
+ alertDownload();
+ for (let i = 0; i < episodeCount; i++) {
+ const res = (await downloadAnimeSeries(item.id, item.slug, i)).data;
+ handleDownloadError(res);
+ }
+};
+
+export const handleTvAnimeEpisodesDownload = async (episodes: Episode[], item: MediaItem) => {
+ alertDownload();
+ for (const episode of episodes) {
+ const res = (await downloadAnimeSeries(item.id, item.slug, episode.episode_id)).data;
+ handleDownloadError(res);
+ }
+
+}
+
+export const handleOVADownload = async (item: MediaItem) => {
+ alertDownload();
+ const res = (await downloadAnimeFilm(item.id, item.slug)).data;
+ handleDownloadError(res);
+};
+
+const handleDownloadError = (res: DownloadResponse) => {
+ if (res.error) {
+ throw new Error(`${res.error} - ${res.message}`);
+ }
+};
+
+export const alertDownload = (message?: any) => {
+ if (message) {
+ alert(message)
+ return;
+ }
+ alert('Il downlaod è iniziato, il file sarà disponibile tra qualche minuto nella cartella \'Video\' del progetto...')
+}
\ No newline at end of file
diff --git a/frontend/src/assets/base.css b/frontend/src/assets/base.css
new file mode 100644
index 0000000..8816868
--- /dev/null
+++ b/frontend/src/assets/base.css
@@ -0,0 +1,86 @@
+/* color palette from */
+:root {
+ --vt-c-white: #ffffff;
+ --vt-c-white-soft: #f8f8f8;
+ --vt-c-white-mute: #f2f2f2;
+
+ --vt-c-black: #181818;
+ --vt-c-black-soft: #222222;
+ --vt-c-black-mute: #282828;
+
+ --vt-c-indigo: #2c3e50;
+
+ --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
+ --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
+ --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
+ --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
+
+ --vt-c-text-light-1: var(--vt-c-indigo);
+ --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
+ --vt-c-text-dark-1: var(--vt-c-white);
+ --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
+}
+
+/* semantic color variables for this project */
+:root {
+ --color-background: var(--vt-c-white);
+ --color-background-soft: var(--vt-c-white-soft);
+ --color-background-mute: var(--vt-c-white-mute);
+
+ --color-border: var(--vt-c-divider-light-2);
+ --color-border-hover: var(--vt-c-divider-light-1);
+
+ --color-heading: var(--vt-c-text-light-1);
+ --color-text: var(--vt-c-text-light-1);
+
+ --section-gap: 160px;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --color-background: var(--vt-c-black);
+ --color-background-soft: var(--vt-c-black-soft);
+ --color-background-mute: var(--vt-c-black-mute);
+
+ --color-border: var(--vt-c-divider-dark-2);
+ --color-border-hover: var(--vt-c-divider-dark-1);
+
+ --color-heading: var(--vt-c-text-dark-1);
+ --color-text: var(--vt-c-text-dark-2);
+ }
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ font-weight: normal;
+}
+
+body {
+ min-height: 100vh;
+ color: var(--color-text);
+ background: var(--color-background);
+ transition:
+ color 0.5s,
+ background-color 0.5s;
+ line-height: 1.6;
+ font-family:
+ Inter,
+ -apple-system,
+ BlinkMacSystemFont,
+ 'Segoe UI',
+ Roboto,
+ Oxygen,
+ Ubuntu,
+ Cantarell,
+ 'Fira Sans',
+ 'Droid Sans',
+ 'Helvetica Neue',
+ sans-serif;
+ font-size: 15px;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
diff --git a/frontend/src/assets/logo.svg b/frontend/src/assets/logo.svg
new file mode 100644
index 0000000..7565660
--- /dev/null
+++ b/frontend/src/assets/logo.svg
@@ -0,0 +1 @@
+
diff --git a/frontend/src/assets/main.css b/frontend/src/assets/main.css
new file mode 100644
index 0000000..36fb845
--- /dev/null
+++ b/frontend/src/assets/main.css
@@ -0,0 +1,35 @@
+@import './base.css';
+
+#app {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ font-weight: normal;
+}
+
+a,
+.green {
+ text-decoration: none;
+ color: hsla(160, 100%, 37%, 1);
+ transition: 0.4s;
+ padding: 3px;
+}
+
+@media (hover: hover) {
+ a:hover {
+ background-color: hsla(160, 100%, 37%, 0.2);
+ }
+}
+
+@media (min-width: 1024px) {
+ body {
+ display: flex;
+ place-items: center;
+ }
+
+ #app {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ padding: 0 2rem;
+ }
+}
diff --git a/frontend/src/components/Card.vue b/frontend/src/components/Card.vue
new file mode 100644
index 0000000..9817f43
--- /dev/null
+++ b/frontend/src/components/Card.vue
@@ -0,0 +1,92 @@
+
+
+
+
+
![]()
+
+ {{ item.name.slice(0, 25) + (item.name.length > 24 ? '...' : '') }}
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/Toggle.vue b/frontend/src/components/Toggle.vue
new file mode 100644
index 0000000..1f31799
--- /dev/null
+++ b/frontend/src/components/Toggle.vue
@@ -0,0 +1,105 @@
+
+
+
+
+ Film/Serie TV
+
+ Anime
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
new file mode 100644
index 0000000..5a5dbdb
--- /dev/null
+++ b/frontend/src/main.ts
@@ -0,0 +1,11 @@
+import './assets/main.css'
+
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+
+const app = createApp(App)
+
+app.use(router)
+
+app.mount('#app')
diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts
new file mode 100644
index 0000000..fbbbafb
--- /dev/null
+++ b/frontend/src/router/index.ts
@@ -0,0 +1,30 @@
+import { createRouter, createWebHistory } from 'vue-router'
+import HomeView from '../views/HomeView.vue'
+import Details from "../views/Details.vue";
+
+const router = createRouter({
+ history: createWebHistory(import.meta.env.BASE_URL),
+ routes: [
+ {
+ path: '/',
+ name: 'home',
+ component: HomeView
+ },
+ {
+ path: '/details:item:imageUrl',
+ name: 'details',
+ component: Details,
+ props: route => {
+ let item;
+ try {
+ item = JSON.parse(route.params.item);
+ } catch (error) {
+ item = {}; // default value
+ }
+ return { item: item, imageUrl: route.params.imageUrl };
+ },
+ }
+ ]
+})
+
+export default router
diff --git a/frontend/src/views/Details.vue b/frontend/src/views/Details.vue
new file mode 100644
index 0000000..5880730
--- /dev/null
+++ b/frontend/src/views/Details.vue
@@ -0,0 +1,335 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Non ci sono episodi...
+
+
+
Episodio {{ episode.number }}
+
+
+
Stagione {{ index + 1 }}
+
+
+
+
+ Episodio {{ episode.number }} -
+ {{episode.name.slice(0, 40) + (episode.name.length > 39 ? '...' : '')}}
+
+
+
+
+
+
+
+
+
+
Questo è un {{item.type}} (QUESTO TESTO E' A SCOPO DI TEST)
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/views/HomeView.vue b/frontend/src/views/HomeView.vue
new file mode 100644
index 0000000..5919c7e
--- /dev/null
+++ b/frontend/src/views/HomeView.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
Nessun risultato trovato
+
+
+
+
\ No newline at end of file
diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json
new file mode 100644
index 0000000..e14c754
--- /dev/null
+++ b/frontend/tsconfig.app.json
@@ -0,0 +1,14 @@
+{
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
+ "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
+ "exclude": ["src/**/__tests__/*"],
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000..66b5e57
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "files": [],
+ "references": [
+ {
+ "path": "./tsconfig.node.json"
+ },
+ {
+ "path": "./tsconfig.app.json"
+ }
+ ]
+}
diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json
new file mode 100644
index 0000000..f094063
--- /dev/null
+++ b/frontend/tsconfig.node.json
@@ -0,0 +1,19 @@
+{
+ "extends": "@tsconfig/node20/tsconfig.json",
+ "include": [
+ "vite.config.*",
+ "vitest.config.*",
+ "cypress.config.*",
+ "nightwatch.conf.*",
+ "playwright.config.*"
+ ],
+ "compilerOptions": {
+ "composite": true,
+ "noEmit": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "types": ["node"]
+ }
+}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
new file mode 100644
index 0000000..5c45e1d
--- /dev/null
+++ b/frontend/vite.config.ts
@@ -0,0 +1,16 @@
+import { fileURLToPath, URL } from 'node:url'
+
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [
+ vue(),
+ ],
+ resolve: {
+ alias: {
+ '@': fileURLToPath(new URL('./src', import.meta.url))
+ }
+ }
+})
diff --git a/kill_gui.sh b/kill_gui.sh
new file mode 100755
index 0000000..c7fac45
--- /dev/null
+++ b/kill_gui.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# Trova i processi che utilizzano la porta 8000
+PROCESSES=$(lsof -i :8000 | awk 'NR!=1 {print $2}')
+
+# Termina i processi trovati
+if [ -n "$PROCESSES" ]; then
+ echo "Terminating processes using port 8000:"
+ for PID in $PROCESSES; do
+ echo "Killing process with PID: $PID"
+ kill -9 $PID
+ done
+else
+ echo "No processes found using port 8000"
+fi
+
+# Trova i processi che utilizzano la porta 5173
+PROCESSES=$(lsof -i :5173 | awk 'NR!=1 {print $2}')
+
+# Termina i processi trovati
+if [ -n "$PROCESSES" ]; then
+ echo "Terminating processes using port 5173:"
+ for PID in $PROCESSES; do
+ echo "Killing process with PID: $PID"
+ kill -9 $PID
+ done
+else
+ echo "No processes found using port 5173"
+fi
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 21218f8..d471fcb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,11 @@
bs4
tqdm
rich
-unidecode
\ No newline at end of file
+unidecode
+ffmpeg-python
+pycryptodome
+m3u8
+lxml
+django==4.2.11
+djangorestframework==3.15.1
+django-cors-headers==4.3.1
\ No newline at end of file
diff --git a/start_gui.sh b/start_gui.sh
new file mode 100755
index 0000000..e339262
--- /dev/null
+++ b/start_gui.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# Installa i pacchetti Python
+echo "Installazione dei pacchetti Python..."
+pip install -r requirements.txt
+
+# Installa i pacchetti npm
+echo "Installazione dei pacchetti npm..."
+cd frontend
+npm install
+cd ..
+
+# Avvia il backend Django
+echo "Avvio del backend Django..."
+python3.11 api/manage.py runserver &
+
+# Avvia il frontend Vue.js con Vite
+echo "Avvio del frontend Vue.js con Vite..."
+cd frontend
+npm run dev &
+
+# Attendi l'esecuzione dei processi
+wait
\ No newline at end of file
From 2abfe82815bdba05591f3f5b1aefc9aef581911e Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Sat, 1 Jun 2024 12:07:36 +0200
Subject: [PATCH 02/13] Restore ...
---
.gitignore | 13 +-
Src/Api/Animeunity/Core/Class/EpisodeType.py | 15 -
Src/Api/Animeunity/Core/Class/PreviewType.py | 13 -
Src/Api/Animeunity/Core/Class/SearchType.py | 23 -
.../Core/Class/EpisodeType.py | 28 -
.../Core/Class/PreviewType.py | 13 -
.../Core/Class/SearchType.py | 34 -
api/__init__.py | 0
api/api/__init__.py | 0
api/api/asgi.py | 16 -
api/api/settings.py | 140 -
api/api/urls.py | 24 -
api/api/wsgi.py | 16 -
api/endpoints/__init__.py | 0
api/endpoints/admin.py | 3 -
api/endpoints/apps.py | 6 -
api/endpoints/migrations/__init__.py | 0
api/endpoints/models.py | 3 -
api/endpoints/tests.py | 3 -
api/endpoints/urls.py | 10 -
api/endpoints/views.py | 241 --
api/manage.py | 24 -
config.json | 2 +-
frontend/.eslintrc.cjs | 15 -
frontend/.gitignore | 30 -
frontend/.prettierrc.json | 8 -
frontend/.vscode/extensions.json | 7 -
frontend/README.md | 39 -
frontend/env.d.ts | 1 -
frontend/index.html | 13 -
frontend/package-lock.json | 3225 -----------------
frontend/package.json | 36 -
frontend/public/favicon.ico | Bin 4286 -> 0 bytes
frontend/src/App.vue | 36 -
frontend/src/api/api.ts | 81 -
frontend/src/api/interfaces.ts | 64 -
frontend/src/api/utils.ts | 63 -
frontend/src/assets/base.css | 86 -
frontend/src/assets/logo.svg | 1 -
frontend/src/assets/main.css | 35 -
frontend/src/components/Card.vue | 92 -
frontend/src/components/Toggle.vue | 105 -
frontend/src/main.ts | 11 -
frontend/src/router/index.ts | 30 -
frontend/src/views/Details.vue | 335 --
frontend/src/views/HomeView.vue | 176 -
frontend/tsconfig.app.json | 14 -
frontend/tsconfig.json | 11 -
frontend/tsconfig.node.json | 19 -
frontend/vite.config.ts | 16 -
kill_gui.sh | 29 -
requirements.txt | 9 +-
start_gui.sh | 23 -
53 files changed, 3 insertions(+), 5234 deletions(-)
delete mode 100644 api/__init__.py
delete mode 100644 api/api/__init__.py
delete mode 100644 api/api/asgi.py
delete mode 100644 api/api/settings.py
delete mode 100644 api/api/urls.py
delete mode 100644 api/api/wsgi.py
delete mode 100644 api/endpoints/__init__.py
delete mode 100644 api/endpoints/admin.py
delete mode 100644 api/endpoints/apps.py
delete mode 100644 api/endpoints/migrations/__init__.py
delete mode 100644 api/endpoints/models.py
delete mode 100644 api/endpoints/tests.py
delete mode 100644 api/endpoints/urls.py
delete mode 100644 api/endpoints/views.py
delete mode 100755 api/manage.py
delete mode 100644 frontend/.eslintrc.cjs
delete mode 100644 frontend/.gitignore
delete mode 100644 frontend/.prettierrc.json
delete mode 100644 frontend/.vscode/extensions.json
delete mode 100644 frontend/README.md
delete mode 100644 frontend/env.d.ts
delete mode 100644 frontend/index.html
delete mode 100644 frontend/package-lock.json
delete mode 100644 frontend/package.json
delete mode 100644 frontend/public/favicon.ico
delete mode 100644 frontend/src/App.vue
delete mode 100644 frontend/src/api/api.ts
delete mode 100644 frontend/src/api/interfaces.ts
delete mode 100644 frontend/src/api/utils.ts
delete mode 100644 frontend/src/assets/base.css
delete mode 100644 frontend/src/assets/logo.svg
delete mode 100644 frontend/src/assets/main.css
delete mode 100644 frontend/src/components/Card.vue
delete mode 100644 frontend/src/components/Toggle.vue
delete mode 100644 frontend/src/main.ts
delete mode 100644 frontend/src/router/index.ts
delete mode 100644 frontend/src/views/Details.vue
delete mode 100644 frontend/src/views/HomeView.vue
delete mode 100644 frontend/tsconfig.app.json
delete mode 100644 frontend/tsconfig.json
delete mode 100644 frontend/tsconfig.node.json
delete mode 100644 frontend/vite.config.ts
delete mode 100755 kill_gui.sh
delete mode 100755 start_gui.sh
diff --git a/.gitignore b/.gitignore
index 69e9099..be44e50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,14 +42,6 @@ local_settings.py
db.sqlite3
db.sqlite3-journal
-
-# Vue stuff:
-frontend/dist/
-frontend/node_modules/
-frontend/npm-debug.log
-frontend/.vite/
-frontend/.vscode/
-
# Jupyter Notebook
.ipynb_checkpoints
@@ -63,7 +55,4 @@ env.bak/
venv.bak/
# Other
-Video
-.idea/
-.vscode/
-.DS_Store
+Video
\ No newline at end of file
diff --git a/Src/Api/Animeunity/Core/Class/EpisodeType.py b/Src/Api/Animeunity/Core/Class/EpisodeType.py
index f583914..14b9694 100644
--- a/Src/Api/Animeunity/Core/Class/EpisodeType.py
+++ b/Src/Api/Animeunity/Core/Class/EpisodeType.py
@@ -45,21 +45,6 @@ class Episode:
def __str__(self):
return f"Episode(id={self.id}, number={self.number}, name='{self.name}', plot='{self.plot}', duration={self.duration} sec)"
-
- def to_dict(self) -> Dict[str, Any]:
- return {
- "id": self.id,
- "number": self.number,
- "name": self.name,
- "plot": self.plot,
- "duration": self.duration,
- "scws_id": self.scws_id,
- "season_id": self.season_id,
- "created_by": self.created_by,
- "created_at": self.created_at,
- "updated_at": self.updated_at,
- "images": [image.__dict__ for image in self.images]
- }
class EpisodeManager:
diff --git a/Src/Api/Animeunity/Core/Class/PreviewType.py b/Src/Api/Animeunity/Core/Class/PreviewType.py
index 7b80b0a..28d741e 100644
--- a/Src/Api/Animeunity/Core/Class/PreviewType.py
+++ b/Src/Api/Animeunity/Core/Class/PreviewType.py
@@ -60,17 +60,4 @@ class PreviewManager:
images_str = "\n".join(str(image) for image in self.images)
return f"Title: ID={self.id}, Type={self.type}, Runtime={self.runtime}, Release Date={self.release_date}, Quality={self.quality}, Plot={self.plot}, Seasons Count={self.seasons_count}\nGenres:\n{genres_str}\nPreview:\n{self.preview}\nImages:\n{images_str}"
- def to_dict(self):
- return {
- "id": self.id,
- "type": self.type,
- "runtime": self.runtime,
- "release_date": self.release_date,
- "quality": self.quality,
- "plot": self.plot,
- "seasons_count": self.seasons_count,
- "genres": [genre.__dict__ for genre in self.genres],
- "preview": self.preview.__dict__,
- "images": [image.__dict__ for image in self.images]
- }
diff --git a/Src/Api/Animeunity/Core/Class/SearchType.py b/Src/Api/Animeunity/Core/Class/SearchType.py
index 4e3c50f..6c492bf 100644
--- a/Src/Api/Animeunity/Core/Class/SearchType.py
+++ b/Src/Api/Animeunity/Core/Class/SearchType.py
@@ -37,33 +37,10 @@ class MediaItem:
self.last_air_date: str = data.get('last_air_date')
self.seasons_count: int = data.get('seasons_count')
self.images: List[Image] = [Image(image_data) for image_data in data.get('images', [])]
- self.comment: str = data.get('comment')
- self.plot: str = data.get('plot')
def __str__(self):
return f"MediaItem(id={self.id}, slug='{self.slug}', name='{self.name}', type='{self.type}', score='{self.score}', sub_ita={self.sub_ita}, last_air_date='{self.last_air_date}', seasons_count={self.seasons_count}, images={self.images})"
- @property
- def to_dict(self) -> dict:
- """
- Convert the MediaItem to a dictionary.
-
- Returns:
- dict: The MediaItem as a dictionary.
- """
- return {
- "id": self.id,
- "slug": self.slug,
- "name": self.name,
- "type": self.type.upper(),
- "score": self.score,
- "sub_ita": self.sub_ita,
- "last_air_date": self.last_air_date,
- "seasons_count": self.seasons_count,
- "images": [image.__dict__ for image in self.images],
- "comment": self.comment,
- "plot": self.plot
- }
class MediaManager:
def __init__(self):
diff --git a/Src/Api/Streamingcommunity/Core/Class/EpisodeType.py b/Src/Api/Streamingcommunity/Core/Class/EpisodeType.py
index 8857726..468e98b 100644
--- a/Src/Api/Streamingcommunity/Core/Class/EpisodeType.py
+++ b/Src/Api/Streamingcommunity/Core/Class/EpisodeType.py
@@ -27,19 +27,6 @@ class Image:
def __str__(self):
return f"Image(id={self.id}, filename='{self.filename}', type='{self.type}', imageable_type='{self.imageable_type}', url='{self.url}')"
-
- def to_dict(self) -> Dict[str, Any]:
- return {
- 'id': self.id,
- 'filename': self.filename,
- 'type': self.type,
- 'imageable_type': self.imageable_type,
- 'imageable_id': self.imageable_id,
- 'created_at': self.created_at,
- 'updated_at': self.updated_at,
- 'original_url_field': self.original_url_field,
- 'url': self.url
- }
class Episode:
@@ -58,21 +45,6 @@ class Episode:
def __str__(self):
return f"Episode(id={self.id}, number={self.number}, name='{self.name}', plot='{self.plot}', duration={self.duration} sec)"
-
- def to_dict(self) -> Dict[str, Any]:
- return {
- 'id': self.id,
- 'number': self.number,
- 'name': self.name,
- 'plot': self.plot,
- 'duration': self.duration,
- 'scws_id': self.scws_id,
- 'season_id': self.season_id,
- 'created_by': self.created_by,
- 'created_at': self.created_at,
- 'updated_at': self.updated_at,
- 'images': [image.to_dict() for image in self.images]
- }
class EpisodeManager:
diff --git a/Src/Api/Streamingcommunity/Core/Class/PreviewType.py b/Src/Api/Streamingcommunity/Core/Class/PreviewType.py
index 7b80b0a..28d741e 100644
--- a/Src/Api/Streamingcommunity/Core/Class/PreviewType.py
+++ b/Src/Api/Streamingcommunity/Core/Class/PreviewType.py
@@ -60,17 +60,4 @@ class PreviewManager:
images_str = "\n".join(str(image) for image in self.images)
return f"Title: ID={self.id}, Type={self.type}, Runtime={self.runtime}, Release Date={self.release_date}, Quality={self.quality}, Plot={self.plot}, Seasons Count={self.seasons_count}\nGenres:\n{genres_str}\nPreview:\n{self.preview}\nImages:\n{images_str}"
- def to_dict(self):
- return {
- "id": self.id,
- "type": self.type,
- "runtime": self.runtime,
- "release_date": self.release_date,
- "quality": self.quality,
- "plot": self.plot,
- "seasons_count": self.seasons_count,
- "genres": [genre.__dict__ for genre in self.genres],
- "preview": self.preview.__dict__,
- "images": [image.__dict__ for image in self.images]
- }
diff --git a/Src/Api/Streamingcommunity/Core/Class/SearchType.py b/Src/Api/Streamingcommunity/Core/Class/SearchType.py
index 4e20c1c..115677d 100644
--- a/Src/Api/Streamingcommunity/Core/Class/SearchType.py
+++ b/Src/Api/Streamingcommunity/Core/Class/SearchType.py
@@ -37,44 +37,10 @@ class MediaItem:
self.last_air_date: str = data.get('last_air_date')
self.seasons_count: int = data.get('seasons_count')
self.images: List[Image] = [Image(image_data) for image_data in data.get('images', [])]
- self.comment: str = data.get('comment')
- self.plot: str = data.get('plot')
def __str__(self):
return f"MediaItem(id={self.id}, slug='{self.slug}', name='{self.name}', type='{self.type}', score='{self.score}', sub_ita={self.sub_ita}, last_air_date='{self.last_air_date}', seasons_count={self.seasons_count}, images={self.images})"
- @property
- def to_dict(self) -> dict:
- """
- Convert the MediaItem to a dictionary.
-
- Returns:
- dict: The MediaItem as a dictionary.
- """
- return {
- "id": self.id,
- "slug": self.slug,
- "name": self.name,
- "type": self.type.upper(),
- "score": self.score,
- "sub_ita": self.sub_ita,
- "last_air_date": self.last_air_date,
- "seasons_count": self.seasons_count,
- "images": [image.__dict__ for image in self.images],
- "comment": self.comment,
- "plot": self.plot
- }
-
- @property
- def get_site_id(self) -> str:
- """
- Get the site ID of the media item.
-
- Returns:
- int: The site ID of the media item.
- """
- return f"{self.id}-{self.slug}"
-
class MediaManager:
def __init__(self):
diff --git a/api/__init__.py b/api/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/api/api/__init__.py b/api/api/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/api/api/asgi.py b/api/api/asgi.py
deleted file mode 100644
index 57b0c31..0000000
--- a/api/api/asgi.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-ASGI config for api project.
-
-It exposes the ASGI callable as a module-level variable named ``application``.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
-"""
-
-import os
-
-from django.core.asgi import get_asgi_application
-
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "api.settings")
-
-application = get_asgi_application()
diff --git a/api/api/settings.py b/api/api/settings.py
deleted file mode 100644
index d64cd0f..0000000
--- a/api/api/settings.py
+++ /dev/null
@@ -1,140 +0,0 @@
-"""
-Django settings for api project.
-
-Generated by 'django-admin startproject' using Django 4.2.7.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/4.2/topics/settings/
-
-For the full list of settings and their values, see
-https://docs.djangoproject.com/en/4.2/ref/settings/
-"""
-
-from pathlib import Path
-
-# Build paths inside the project like this: BASE_DIR / 'subdir'.
-BASE_DIR = Path(__file__).resolve().parent.parent
-
-
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = "django-insecure-7u!h-#6b--%h8()19so$s+t9cjh5y1+ljnqum*@gm))0(a_qka"
-
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True
-
-ALLOWED_HOSTS = []
-
-
-# Application definition
-
-INSTALLED_APPS = [
- "django.contrib.admin",
- "django.contrib.auth",
- "django.contrib.contenttypes",
- "django.contrib.sessions",
- "django.contrib.messages",
- "django.contrib.staticfiles",
- "corsheaders",
- "endpoints",
- "rest_framework",
-]
-
-MIDDLEWARE = [
- "corsheaders.middleware.CorsMiddleware",
- "django.middleware.security.SecurityMiddleware",
- "django.contrib.sessions.middleware.SessionMiddleware",
- "django.middleware.common.CommonMiddleware",
- "django.middleware.csrf.CsrfViewMiddleware",
- "django.contrib.auth.middleware.AuthenticationMiddleware",
- "django.contrib.messages.middleware.MessageMiddleware",
- "django.middleware.clickjacking.XFrameOptionsMiddleware",
-]
-
-ROOT_URLCONF = "api.urls"
-
-TEMPLATES = [
- {
- "BACKEND": "django.template.backends.django.DjangoTemplates",
- "DIRS": [],
- "APP_DIRS": True,
- "OPTIONS": {
- "context_processors": [
- "django.template.context_processors.debug",
- "django.template.context_processors.request",
- "django.contrib.auth.context_processors.auth",
- "django.contrib.messages.context_processors.messages",
- ],
- },
- },
-]
-
-WSGI_APPLICATION = "api.wsgi.application"
-
-
-# Database
-# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
-
-DATABASES = {
- "default": {
- "ENGINE": "django.db.backends.sqlite3",
- "NAME": BASE_DIR / "db.sqlite3",
- }
-}
-
-
-# Password validation
-# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
-
-AUTH_PASSWORD_VALIDATORS = [
- {
- "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
- },
- {
- "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
- },
- {
- "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
- },
- {
- "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
- },
-]
-
-
-# Internationalization
-# https://docs.djangoproject.com/en/4.2/topics/i18n/
-
-LANGUAGE_CODE = "en-us"
-
-TIME_ZONE = "UTC"
-
-USE_I18N = True
-
-USE_TZ = True
-
-
-# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/4.2/howto/static-files/
-
-STATIC_URL = "static/"
-
-# Default primary key field type
-# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
-
-DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
-
-CORS_ALLOWED_ORIGINS = [
- "http://localhost:5173",
-]
-
-CORS_ALLOWED_METHODS = (
- "DELETE",
- "GET",
- "OPTIONS",
- "PATCH",
- "POST",
- "PUT",
-)
diff --git a/api/api/urls.py b/api/api/urls.py
deleted file mode 100644
index 30b52fe..0000000
--- a/api/api/urls.py
+++ /dev/null
@@ -1,24 +0,0 @@
-"""
-URL configuration for api project.
-
-The `urlpatterns` list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/4.2/topics/http/urls/
-Examples:
-Function views
- 1. Add an import: from my_app import views
- 2. Add a URL to urlpatterns: path('', views.home, name='home')
-Class-based views
- 1. Add an import: from other_app.views import Home
- 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
-Including another URLconf
- 1. Import the include() function: from django.urls import include, path
- 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
-"""
-
-from django.contrib import admin
-from django.urls import path, include
-
-urlpatterns = [
- path("admin/", admin.site.urls),
- path("api/", include("endpoints.urls")),
-]
diff --git a/api/api/wsgi.py b/api/api/wsgi.py
deleted file mode 100644
index bfbc45a..0000000
--- a/api/api/wsgi.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-WSGI config for api project.
-
-It exposes the WSGI callable as a module-level variable named ``application``.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
-"""
-
-import os
-
-from django.core.wsgi import get_wsgi_application
-
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "api.settings")
-
-application = get_wsgi_application()
diff --git a/api/endpoints/__init__.py b/api/endpoints/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/api/endpoints/admin.py b/api/endpoints/admin.py
deleted file mode 100644
index 8c38f3f..0000000
--- a/api/endpoints/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/api/endpoints/apps.py b/api/endpoints/apps.py
deleted file mode 100644
index 0cf6cd7..0000000
--- a/api/endpoints/apps.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from django.apps import AppConfig
-
-
-class EndpointsConfig(AppConfig):
- default_auto_field = "django.db.models.BigAutoField"
- name = "endpoints"
diff --git a/api/endpoints/migrations/__init__.py b/api/endpoints/migrations/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/api/endpoints/models.py b/api/endpoints/models.py
deleted file mode 100644
index 71a8362..0000000
--- a/api/endpoints/models.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.db import models
-
-# Create your models here.
diff --git a/api/endpoints/tests.py b/api/endpoints/tests.py
deleted file mode 100644
index 7ce503c..0000000
--- a/api/endpoints/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/api/endpoints/urls.py b/api/endpoints/urls.py
deleted file mode 100644
index 184bb2f..0000000
--- a/api/endpoints/urls.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from rest_framework import routers
-
-from .views import SearchView#, DownloadView
-
-router = routers.DefaultRouter()
-
-router.register(r"search", SearchView, basename="search")
-#router.register(r"download", DownloadView, basename="download")
-
-urlpatterns = router.urls
diff --git a/api/endpoints/views.py b/api/endpoints/views.py
deleted file mode 100644
index 0df7062..0000000
--- a/api/endpoints/views.py
+++ /dev/null
@@ -1,241 +0,0 @@
-import json
-import os
-
-from django.http import StreamingHttpResponse
-
-from rest_framework import viewsets
-from rest_framework.decorators import action
-from rest_framework.response import Response
-
-from Src.Api.Animeunity import title_search as anime_search
-from Src.Api.Animeunity.Core.Vix_player.player import VideoSource as anime_source
-from Src.Api.Animeunity.site import media_search_manager as anime_media_manager
-
-from Src.Api.Streamingcommunity import title_search as sc_search, get_version_and_domain
-from Src.Api.Streamingcommunity.Core.Vix_player.player import VideoSource as film_video_source
-from Src.Api.Streamingcommunity.site import media_search_manager as film_media_manager
-
-
-class SearchView(viewsets.ViewSet):
-
- def list(self, request):
- self.search_query = request.query_params.get("search_terms")
- self.type_search = request.query_params.get("type")
-
- media_manager = anime_media_manager if self.type_search == "anime" else film_media_manager
- media_manager.media_list = []
- self.len_database = 0
- if self.type_search == "film":
- _, self.domain = get_version_and_domain()
- self.len_database = sc_search(self.search_query, self.domain)
- elif self.type_search == "anime":
- self.len_database = anime_search(self.search_query)
-
- media_list = media_manager.media_list
-
- if self.len_database != 0:
- data_to_return = []
- for _, media in enumerate(media_list):
- if self.type_search == "anime":
- if media.type == "TV":
- media.type = "TV_ANIME"
- if media.type == "Movie":
- media.type = "OVA"
- data_to_return.append(media.to_dict)
-
- return Response({"media": data_to_return})
-
- return Response({"error": "No media found with that search query"})
-
- @action(detail=False, methods=["get"])
- def get_episodes_info(self, request):
- self.media_id = request.query_params.get("media_id")
- self.media_slug = request.query_params.get("media_slug")
- self.type_media = request.query_params.get("type_media")
-
- try:
- match self.type_media:
- case "TV":
-
- def stream_episodes():
- self.version, self.domain = get_version_and_domain()
-
- video_source = film_video_source()
- video_source.setup(
- version=self.version,
- domain=self.domain,
- media_id=self.media_id,
- series_name=self.media_slug
- )
- video_source.collect_info_seasons()
- seasons_count = video_source.obj_title_manager.get_length()
-
- episodes = {}
- for i_season in range(1, seasons_count + 1):
- video_source.obj_episode_manager.clear()
- video_source.collect_title_season(i_season)
- episodes_count = (
- video_source.obj_episode_manager.get_length()
- )
- episodes[i_season] = {}
- for i_episode in range(1, episodes_count + 1):
- episode = video_source.obj_episode_manager.episodes[
- i_episode - 1
- ]
- episodes[i_season][i_episode] = episode.to_dict()
-
- yield f'{json.dumps({"episodes": episodes})}\n\n'
-
- response = StreamingHttpResponse(
- stream_episodes(), content_type="text/event-stream"
- )
- return response
-
- case "TV_ANIME":
- def stream_episodes():
- video_source = anime_source()
- video_source.setup(
- media_id = self.media_id,
- series_name = self.media_slug
- )
- episoded_count = video_source.get_count_episodes()
-
- for i in range(0, episoded_count):
- episode_info = video_source.get_info_episode(i).to_dict()
- episode_info["episode_id"] = i
- episode_info["episode_total"] = episoded_count
- print(f"Getting episode {i} of {episoded_count} info...")
- yield f"{json.dumps(episode_info)}\n\n"
-
- response = StreamingHttpResponse(
- stream_episodes(), content_type="text/event-stream"
- )
- return response
-
- except Exception as e:
- return Response(
- {
- "error": "Error while getting episodes info",
- "message": str(e),
- }
- )
-
- return Response({"error": "No media found with that search query"})
-
- @action(detail=False, methods=["get"])
- def get_preview(self, request):
- self.media_id = request.query_params.get("media_id")
- self.media_slug = request.query_params.get("media_slug")
- self.type_media = request.query_params.get("type_media")
-
- try:
- if self.type_media in ["TV", "MOVIE"]:
- version, domain = get_version_and_domain()
- video_source = film_video_source()
- video_source.setup(media_id=self.media_id, version=version, domain=domain, series_name=self.media_slug)
- video_source.get_preview()
- return Response(video_source.obj_preview.to_dict())
- if self.type_media in ["TV_ANIME", "OVA", "SPECIAL"]:
- video_source = anime_source()
- video_source.setup(media_id=self.media_id, series_name=self.media_slug)
- video_source.get_preview()
- return Response(video_source.obj_preview.to_dict())
- except Exception as e:
- return Response(
- {
- "error": "Error while getting preview info",
- "message": str(e),
- }
- )
-
- return Response({"error": "No media found with that search query"})
-
-
-'''
-class DownloadView(viewsets.ViewSet):
-
- def create(self, request):
- self.media_id = request.data.get("media_id")
- self.media_slug = request.data.get("media_slug")
- self.type_media = request.data.get("type_media").upper()
- self.download_id = request.data.get("download_id")
- self.tv_series_episode_id = request.data.get("tv_series_episode_id")
-
- if self.type_media in ["TV", "MOVIE"]:
- self.site_version, self.domain = get_version_and_domain()
-
- response_dict = {"error": "No media found with that search query"}
-
- try:
- match self.type_media:
- case "MOVIE":
- download_film(self.media_id, self.media_slug, self.domain)
- case "TV":
- video_source = VideoSource()
- video_source.set_url_base_name(STREAM_SITE_NAME)
- video_source.set_version(self.site_version)
- video_source.set_domain(self.domain)
- video_source.set_series_name(self.media_slug)
- video_source.set_media_id(self.media_id)
-
- video_source.collect_info_seasons()
- video_source.obj_episode_manager.clear()
-
- video_source.collect_title_season(self.download_id)
- episodes_count = video_source.obj_episode_manager.get_length()
- for i_episode in range(1, episodes_count + 1):
- episode_id = video_source.obj_episode_manager.episodes[
- i_episode - 1
- ].id
-
- # Define filename and path for the downloaded video
- mp4_name = remove_special_characters(
- f"{map_episode_title(self.media_slug,video_source.obj_episode_manager.episodes[i_episode - 1],self.download_id)}.mp4"
- )
- mp4_path = remove_special_characters(
- os.path.join(
- ROOT_PATH,
- SERIES_FOLDER,
- self.media_slug,
- f"S{self.download_id}",
- )
- )
- os.makedirs(mp4_path, exist_ok=True)
-
- # Get iframe and content for the episode
- video_source.get_iframe(episode_id)
- video_source.get_content()
- video_source.set_url_base_name(STREAM_SITE_NAME)
-
- # Download the episode
- obj_download = Downloader(
- m3u8_playlist=video_source.get_playlist(),
- key=video_source.get_key(),
- output_filename=os.path.join(mp4_path, mp4_name),
- )
-
- obj_download.download_m3u8()
-
- case "TV_ANIME":
- episodes_downloader = EpisodeDownloader(
- self.media_id, self.media_slug
- )
- episodes_downloader.download_episode(self.download_id)
- case "OVA" | "SPECIAL":
- anime_download_film(
- id_film=self.media_id, title_name=self.media_slug
- )
- case _:
- raise Exception("Type media not supported")
-
- response_dict = {
- "message": "Download done, it is saved in Video folder inside project root"
- }
- except Exception as e:
- response_dict = {
- "error": "Error while downloading the media",
- "message": str(e),
- }
-
- return Response(response_dict)
-'''
diff --git a/api/manage.py b/api/manage.py
deleted file mode 100755
index 3b72e09..0000000
--- a/api/manage.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python
-"""Django's command-line utility for administrative tasks."""
-import os
-import sys
-
-sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
-
-
-def main():
- """Run administrative tasks."""
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "api.settings")
- try:
- from django.core.management import execute_from_command_line
- except ImportError as exc:
- raise ImportError(
- "Couldn't import Django. Are you sure it's installed and "
- "available on your PYTHONPATH environment variable? Did you "
- "forget to activate a virtual environment?"
- ) from exc
- execute_from_command_line(sys.argv)
-
-
-if __name__ == "__main__":
- main()
diff --git a/config.json b/config.json
index c2bc0e2..2603713 100644
--- a/config.json
+++ b/config.json
@@ -45,4 +45,4 @@
"animeunity": "to",
"altadefinizione": "food"
}
-}
\ No newline at end of file
+}
diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs
deleted file mode 100644
index 6f40582..0000000
--- a/frontend/.eslintrc.cjs
+++ /dev/null
@@ -1,15 +0,0 @@
-/* eslint-env node */
-require('@rushstack/eslint-patch/modern-module-resolution')
-
-module.exports = {
- root: true,
- 'extends': [
- 'plugin:vue/vue3-essential',
- 'eslint:recommended',
- '@vue/eslint-config-typescript',
- '@vue/eslint-config-prettier/skip-formatting'
- ],
- parserOptions: {
- ecmaVersion: 'latest'
- }
-}
diff --git a/frontend/.gitignore b/frontend/.gitignore
deleted file mode 100644
index 8ee54e8..0000000
--- a/frontend/.gitignore
+++ /dev/null
@@ -1,30 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-.DS_Store
-dist
-dist-ssr
-coverage
-*.local
-
-/cypress/videos/
-/cypress/screenshots/
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
-
-*.tsbuildinfo
diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json
deleted file mode 100644
index 66e2335..0000000
--- a/frontend/.prettierrc.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "$schema": "https://json.schemastore.org/prettierrc",
- "semi": false,
- "tabWidth": 2,
- "singleQuote": true,
- "printWidth": 100,
- "trailingComma": "none"
-}
\ No newline at end of file
diff --git a/frontend/.vscode/extensions.json b/frontend/.vscode/extensions.json
deleted file mode 100644
index 93ea3e7..0000000
--- a/frontend/.vscode/extensions.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "recommendations": [
- "Vue.volar",
- "dbaeumer.vscode-eslint",
- "esbenp.prettier-vscode"
- ]
-}
diff --git a/frontend/README.md b/frontend/README.md
deleted file mode 100644
index 9b4c74c..0000000
--- a/frontend/README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# frontend
-
-This template should help get you started developing with Vue 3 in Vite.
-
-## Recommended IDE Setup
-
-[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
-
-## Type Support for `.vue` Imports in TS
-
-TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
-
-## Customize configuration
-
-See [Vite Configuration Reference](https://vitejs.dev/config/).
-
-## Project Setup
-
-```sh
-npm install
-```
-
-### Compile and Hot-Reload for Development
-
-```sh
-npm run dev
-```
-
-### Type-Check, Compile and Minify for Production
-
-```sh
-npm run build
-```
-
-### Lint with [ESLint](https://eslint.org/)
-
-```sh
-npm run lint
-```
diff --git a/frontend/env.d.ts b/frontend/env.d.ts
deleted file mode 100644
index 11f02fe..0000000
--- a/frontend/env.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-///
diff --git a/frontend/index.html b/frontend/index.html
deleted file mode 100644
index a888544..0000000
--- a/frontend/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
- Vite App
-
-
-
-
-
-
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
deleted file mode 100644
index dd00361..0000000
--- a/frontend/package-lock.json
+++ /dev/null
@@ -1,3225 +0,0 @@
-{
- "name": "frontend",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "frontend",
- "version": "0.0.0",
- "dependencies": {
- "axios": "^1.6.8",
- "vue": "^3.4.21",
- "vue-router": "^4.3.0"
- },
- "devDependencies": {
- "@rushstack/eslint-patch": "^1.8.0",
- "@tsconfig/node20": "^20.1.4",
- "@types/node": "^20.12.5",
- "@vitejs/plugin-vue": "^5.0.4",
- "@vue/eslint-config-prettier": "^9.0.0",
- "@vue/eslint-config-typescript": "^13.0.0",
- "@vue/tsconfig": "^0.5.1",
- "eslint": "^8.57.0",
- "eslint-plugin-vue": "^9.23.0",
- "npm-run-all2": "^6.1.2",
- "prettier": "^3.2.5",
- "typescript": "~5.4.0",
- "vite": "^5.2.8",
- "vue-tsc": "^2.0.11"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.24.4",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz",
- "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==",
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
- "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
- "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
- "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
- "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
- "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
- "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
- "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
- "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
- "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
- "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
- "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
- "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
- "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
- "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
- "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
- "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
- "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
- "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
- "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
- "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
- "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
- "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
- "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@eslint-community/eslint-utils": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
- "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
- "dev": true,
- "dependencies": {
- "eslint-visitor-keys": "^3.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
- }
- },
- "node_modules/@eslint-community/regexpp": {
- "version": "4.10.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
- "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
- "dev": true,
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/@eslint/eslintrc": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
- "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
- "dev": true,
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^9.6.0",
- "globals": "^13.19.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/@eslint/js": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
- "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
- "dev": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/@humanwhocodes/config-array": {
- "version": "0.11.14",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
- "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
- "dev": true,
- "dependencies": {
- "@humanwhocodes/object-schema": "^2.0.2",
- "debug": "^4.3.1",
- "minimatch": "^3.0.5"
- },
- "engines": {
- "node": ">=10.10.0"
- }
- },
- "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
- "dev": true,
- "engines": {
- "node": ">=12.22"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
- }
- },
- "node_modules/@humanwhocodes/object-schema": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
- "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
- "dev": true
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@pkgr/core": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
- "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
- "dev": true,
- "engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/unts"
- }
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.0.tgz",
- "integrity": "sha512-nNvLvC2fjC+3+bHYN9uaGF3gcyy7RHGZhtl8TB/kINj9hiOQza8kWJGZh47GRPMrqeseO8U+Z8ElDMCZlWBdHA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.0.tgz",
- "integrity": "sha512-+kjt6dvxnyTIAo7oHeYseYhDyZ7xRKTNl/FoQI96PHkJVxoChldJnne/LzYqpqidoK1/0kX0/q+5rrYqjpth6w==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.0.tgz",
- "integrity": "sha512-Oj6Tp0unMpGTBjvNwbSRv3DopMNLu+mjBzhKTt2zLbDJ/45fB1pltr/rqrO4bE95LzuYwhYn127pop+x/pzf5w==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.0.tgz",
- "integrity": "sha512-3nJx0T+yptxMd+v93rBRxSPTAVCv8szu/fGZDJiKX7kvRe9sENj2ggXjCH/KK1xZEmJOhaNo0c9sGMgGdfkvEw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.0.tgz",
- "integrity": "sha512-Vb2e8p9b2lxxgqyOlBHmp6hJMu/HSU6g//6Tbr7x5V1DlPCHWLOm37nSIVK314f+IHzORyAQSqL7+9tELxX3zQ==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.0.tgz",
- "integrity": "sha512-Md60KsmC5ZIaRq/bYYDloklgU+XLEZwS2EXXVcSpiUw+13/ZASvSWQ/P92rQ9YDCL6EIoXxuQ829JkReqdYbGg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.0.tgz",
- "integrity": "sha512-zL5rBFtJ+2EGnMRm2TqKjdjgFqlotSU+ZJEN37nV+fiD3I6Gy0dUh3jBWN0wSlcXVDEJYW7YBe+/2j0N9unb2w==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.0.tgz",
- "integrity": "sha512-s2xAyNkJqUdtRVgNK4NK4P9QttS538JuX/kfVQOdZDI5FIKVAUVdLW7qhGfmaySJ1EvN/Bnj9oPm5go9u8navg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.0.tgz",
- "integrity": "sha512-7F99yzVT67B7IUNMjLD9QCFDCyHkyCJMS1dywZrGgVFJao4VJ9szrIEgH67cR+bXQgEaY01ur/WSL6B0jtcLyA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.0.tgz",
- "integrity": "sha512-leFtyiXisfa3Sg9pgZJwRKITWnrQfhtqDjCamnZhkZuIsk1FXmYwKoTkp6lsCgimIcneFFkHKp/yGLxDesga4g==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.0.tgz",
- "integrity": "sha512-FtOgui6qMJ4jbSXTxElsy/60LEe/3U0rXkkz2G5CJ9rbHPAvjMvI+3qF0A0fwLQ5hW+/ZC6PbnS2KfRW9JkgDQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.0.tgz",
- "integrity": "sha512-v6eiam/1w3HUfU/ZjzIDodencqgrSqzlNuNtiwH7PFJHYSo1ezL0/UIzmS2lpSJF1ORNaplXeKHYmmdt81vV2g==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.0.tgz",
- "integrity": "sha512-OUhkSdpM5ofVlVU2k4CwVubYwiwu1a4jYWPpubzN7Vzao73GoPBowHcCfaRSFRz1SszJ3HIsk3dZYk4kzbqjgw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.0.tgz",
- "integrity": "sha512-uL7UYO/MNJPGL/yflybI+HI+n6+4vlfZmQZOCb4I+z/zy1wisHT3exh7oNQsnL6Eso0EUTEfgQ/PaGzzXf6XyQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.0.tgz",
- "integrity": "sha512-4WnSgaUiUmXILwFqREdOcqvSj6GD/7FrvSjhaDjmwakX9w4Z2F8JwiSP1AZZbuRkPqzi444UI5FPv33VKOWYFQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.0.tgz",
- "integrity": "sha512-ve+D8t1prRSRnF2S3pyDtTXDlvW1Pngbz76tjgYFQW1jxVSysmQCZfPoDAo4WP+Ano8zeYp85LsArZBI12HfwQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rushstack/eslint-patch": {
- "version": "1.10.2",
- "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.2.tgz",
- "integrity": "sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==",
- "dev": true
- },
- "node_modules/@tsconfig/node20": {
- "version": "20.1.4",
- "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.4.tgz",
- "integrity": "sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==",
- "dev": true
- },
- "node_modules/@types/estree": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
- "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
- "dev": true
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true
- },
- "node_modules/@types/node": {
- "version": "20.12.7",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz",
- "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==",
- "dev": true,
- "dependencies": {
- "undici-types": "~5.26.4"
- }
- },
- "node_modules/@types/semver": {
- "version": "7.5.8",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
- "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
- "dev": true
- },
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.7.1.tgz",
- "integrity": "sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==",
- "dev": true,
- "dependencies": {
- "@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "7.7.1",
- "@typescript-eslint/type-utils": "7.7.1",
- "@typescript-eslint/utils": "7.7.1",
- "@typescript-eslint/visitor-keys": "7.7.1",
- "debug": "^4.3.4",
- "graphemer": "^1.4.0",
- "ignore": "^5.3.1",
- "natural-compare": "^1.4.0",
- "semver": "^7.6.0",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^7.0.0",
- "eslint": "^8.56.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/parser": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.7.1.tgz",
- "integrity": "sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/scope-manager": "7.7.1",
- "@typescript-eslint/types": "7.7.1",
- "@typescript-eslint/typescript-estree": "7.7.1",
- "@typescript-eslint/visitor-keys": "7.7.1",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.56.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.7.1.tgz",
- "integrity": "sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "7.7.1",
- "@typescript-eslint/visitor-keys": "7.7.1"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/type-utils": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.7.1.tgz",
- "integrity": "sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/typescript-estree": "7.7.1",
- "@typescript-eslint/utils": "7.7.1",
- "debug": "^4.3.4",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.56.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/types": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.7.1.tgz",
- "integrity": "sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==",
- "dev": true,
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.7.1.tgz",
- "integrity": "sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "7.7.1",
- "@typescript-eslint/visitor-keys": "7.7.1",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "minimatch": "^9.0.4",
- "semver": "^7.6.0",
- "ts-api-utils": "^1.3.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/utils": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.7.1.tgz",
- "integrity": "sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.4.0",
- "@types/json-schema": "^7.0.15",
- "@types/semver": "^7.5.8",
- "@typescript-eslint/scope-manager": "7.7.1",
- "@typescript-eslint/types": "7.7.1",
- "@typescript-eslint/typescript-estree": "7.7.1",
- "semver": "^7.6.0"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.56.0"
- }
- },
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.7.1.tgz",
- "integrity": "sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "7.7.1",
- "eslint-visitor-keys": "^3.4.3"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@ungap/structured-clone": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
- "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
- "dev": true
- },
- "node_modules/@vitejs/plugin-vue": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
- "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==",
- "dev": true,
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "peerDependencies": {
- "vite": "^5.0.0",
- "vue": "^3.2.25"
- }
- },
- "node_modules/@volar/language-core": {
- "version": "2.2.0-alpha.10",
- "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.2.0-alpha.10.tgz",
- "integrity": "sha512-njVJLtpu0zMvDaEk7K5q4BRpOgbyEUljU++un9TfJoJNhxG0z/hWwpwgTRImO42EKvwIxF3XUzeMk+qatAFy7Q==",
- "dev": true,
- "dependencies": {
- "@volar/source-map": "2.2.0-alpha.10"
- }
- },
- "node_modules/@volar/source-map": {
- "version": "2.2.0-alpha.10",
- "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.2.0-alpha.10.tgz",
- "integrity": "sha512-nrdWApVkP5cksAnDEyy1JD9rKdwOJsEq1B+seWO4vNXmZNcxQQCx4DULLBvKt7AzRUAQiAuw5aQkb9RBaSqdVA==",
- "dev": true,
- "dependencies": {
- "muggle-string": "^0.4.0"
- }
- },
- "node_modules/@volar/typescript": {
- "version": "2.2.0-alpha.10",
- "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.2.0-alpha.10.tgz",
- "integrity": "sha512-GCa0vTVVdA9ULUsu2Rx7jwsIuyZQPvPVT9o3NrANTbYv+523Ao1gv3glC5vzNSDPM6bUl37r94HbCj7KINQr+g==",
- "dev": true,
- "dependencies": {
- "@volar/language-core": "2.2.0-alpha.10",
- "path-browserify": "^1.0.1"
- }
- },
- "node_modules/@vue/compiler-core": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.25.tgz",
- "integrity": "sha512-Y2pLLopaElgWnMNolgG8w3C5nNUVev80L7hdQ5iIKPtMJvhVpG0zhnBG/g3UajJmZdvW0fktyZTotEHD1Srhbg==",
- "dependencies": {
- "@babel/parser": "^7.24.4",
- "@vue/shared": "3.4.25",
- "entities": "^4.5.0",
- "estree-walker": "^2.0.2",
- "source-map-js": "^1.2.0"
- }
- },
- "node_modules/@vue/compiler-dom": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.25.tgz",
- "integrity": "sha512-Ugz5DusW57+HjllAugLci19NsDK+VyjGvmbB2TXaTcSlQxwL++2PETHx/+Qv6qFwNLzSt7HKepPe4DcTE3pBWg==",
- "dependencies": {
- "@vue/compiler-core": "3.4.25",
- "@vue/shared": "3.4.25"
- }
- },
- "node_modules/@vue/compiler-sfc": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.25.tgz",
- "integrity": "sha512-m7rryuqzIoQpOBZ18wKyq05IwL6qEpZxFZfRxlNYuIPDqywrXQxgUwLXIvoU72gs6cRdY6wHD0WVZIFE4OEaAQ==",
- "dependencies": {
- "@babel/parser": "^7.24.4",
- "@vue/compiler-core": "3.4.25",
- "@vue/compiler-dom": "3.4.25",
- "@vue/compiler-ssr": "3.4.25",
- "@vue/shared": "3.4.25",
- "estree-walker": "^2.0.2",
- "magic-string": "^0.30.10",
- "postcss": "^8.4.38",
- "source-map-js": "^1.2.0"
- }
- },
- "node_modules/@vue/compiler-ssr": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.25.tgz",
- "integrity": "sha512-H2ohvM/Pf6LelGxDBnfbbXFPyM4NE3hrw0e/EpwuSiYu8c819wx+SVGdJ65p/sFrYDd6OnSDxN1MB2mN07hRSQ==",
- "dependencies": {
- "@vue/compiler-dom": "3.4.25",
- "@vue/shared": "3.4.25"
- }
- },
- "node_modules/@vue/devtools-api": {
- "version": "6.6.1",
- "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz",
- "integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA=="
- },
- "node_modules/@vue/eslint-config-prettier": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
- "integrity": "sha512-z1ZIAAUS9pKzo/ANEfd2sO+v2IUalz7cM/cTLOZ7vRFOPk5/xuRKQteOu1DErFLAh/lYGXMVZ0IfYKlyInuDVg==",
- "dev": true,
- "dependencies": {
- "eslint-config-prettier": "^9.0.0",
- "eslint-plugin-prettier": "^5.0.0"
- },
- "peerDependencies": {
- "eslint": ">= 8.0.0",
- "prettier": ">= 3.0.0"
- }
- },
- "node_modules/@vue/eslint-config-typescript": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-13.0.0.tgz",
- "integrity": "sha512-MHh9SncG/sfqjVqjcuFLOLD6Ed4dRAis4HNt0dXASeAuLqIAx4YMB1/m2o4pUKK1vCt8fUvYG8KKX2Ot3BVZTg==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/eslint-plugin": "^7.1.1",
- "@typescript-eslint/parser": "^7.1.1",
- "vue-eslint-parser": "^9.3.1"
- },
- "engines": {
- "node": "^18.18.0 || >=20.0.0"
- },
- "peerDependencies": {
- "eslint": "^8.56.0",
- "eslint-plugin-vue": "^9.0.0",
- "typescript": ">=4.7.4"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@vue/language-core": {
- "version": "2.0.14",
- "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.14.tgz",
- "integrity": "sha512-3q8mHSNcGTR7sfp2X6jZdcb4yt8AjBXAfKk0qkZIh7GAJxOnoZ10h5HToZglw4ToFvAnq+xu/Z2FFbglh9Icag==",
- "dev": true,
- "dependencies": {
- "@volar/language-core": "2.2.0-alpha.10",
- "@vue/compiler-dom": "^3.4.0",
- "@vue/shared": "^3.4.0",
- "computeds": "^0.0.1",
- "minimatch": "^9.0.3",
- "path-browserify": "^1.0.1",
- "vue-template-compiler": "^2.7.14"
- },
- "peerDependencies": {
- "typescript": "*"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@vue/reactivity": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.25.tgz",
- "integrity": "sha512-mKbEtKr1iTxZkAG3vm3BtKHAOhuI4zzsVcN0epDldU/THsrvfXRKzq+lZnjczZGnTdh3ojd86/WrP+u9M51pWQ==",
- "dependencies": {
- "@vue/shared": "3.4.25"
- }
- },
- "node_modules/@vue/runtime-core": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.25.tgz",
- "integrity": "sha512-3qhsTqbEh8BMH3pXf009epCI5E7bKu28fJLi9O6W+ZGt/6xgSfMuGPqa5HRbUxLoehTNp5uWvzCr60KuiRIL0Q==",
- "dependencies": {
- "@vue/reactivity": "3.4.25",
- "@vue/shared": "3.4.25"
- }
- },
- "node_modules/@vue/runtime-dom": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.25.tgz",
- "integrity": "sha512-ode0sj77kuwXwSc+2Yhk8JMHZh1sZp9F/51wdBiz3KGaWltbKtdihlJFhQG4H6AY+A06zzeMLkq6qu8uDSsaoA==",
- "dependencies": {
- "@vue/runtime-core": "3.4.25",
- "@vue/shared": "3.4.25",
- "csstype": "^3.1.3"
- }
- },
- "node_modules/@vue/server-renderer": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.25.tgz",
- "integrity": "sha512-8VTwq0Zcu3K4dWV0jOwIVINESE/gha3ifYCOKEhxOj6MEl5K5y8J8clQncTcDhKF+9U765nRw4UdUEXvrGhyVQ==",
- "dependencies": {
- "@vue/compiler-ssr": "3.4.25",
- "@vue/shared": "3.4.25"
- },
- "peerDependencies": {
- "vue": "3.4.25"
- }
- },
- "node_modules/@vue/shared": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.25.tgz",
- "integrity": "sha512-k0yappJ77g2+KNrIaF0FFnzwLvUBLUYr8VOwz+/6vLsmItFp51AcxLL7Ey3iPd7BIRyWPOcqUjMnm7OkahXllA=="
- },
- "node_modules/@vue/tsconfig": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz",
- "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==",
- "dev": true
- },
- "node_modules/acorn": {
- "version": "8.11.3",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
- "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
- },
- "node_modules/axios": {
- "version": "1.6.8",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
- "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
- "dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.0",
- "proxy-from-env": "^1.1.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
- },
- "node_modules/boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
- "dev": true
- },
- "node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "dependencies": {
- "fill-range": "^7.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/computeds": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz",
- "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==",
- "dev": true
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "dev": true,
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/csstype": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
- },
- "node_modules/de-indent": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
- "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
- "dev": true
- },
- "node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dev": true,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "dependencies": {
- "path-type": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/esbuild": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
- "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.20.2",
- "@esbuild/android-arm": "0.20.2",
- "@esbuild/android-arm64": "0.20.2",
- "@esbuild/android-x64": "0.20.2",
- "@esbuild/darwin-arm64": "0.20.2",
- "@esbuild/darwin-x64": "0.20.2",
- "@esbuild/freebsd-arm64": "0.20.2",
- "@esbuild/freebsd-x64": "0.20.2",
- "@esbuild/linux-arm": "0.20.2",
- "@esbuild/linux-arm64": "0.20.2",
- "@esbuild/linux-ia32": "0.20.2",
- "@esbuild/linux-loong64": "0.20.2",
- "@esbuild/linux-mips64el": "0.20.2",
- "@esbuild/linux-ppc64": "0.20.2",
- "@esbuild/linux-riscv64": "0.20.2",
- "@esbuild/linux-s390x": "0.20.2",
- "@esbuild/linux-x64": "0.20.2",
- "@esbuild/netbsd-x64": "0.20.2",
- "@esbuild/openbsd-x64": "0.20.2",
- "@esbuild/sunos-x64": "0.20.2",
- "@esbuild/win32-arm64": "0.20.2",
- "@esbuild/win32-ia32": "0.20.2",
- "@esbuild/win32-x64": "0.20.2"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
- "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.6.1",
- "@eslint/eslintrc": "^2.1.4",
- "@eslint/js": "8.57.0",
- "@humanwhocodes/config-array": "^0.11.14",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@nodelib/fs.walk": "^1.2.8",
- "@ungap/structured-clone": "^1.2.0",
- "ajv": "^6.12.4",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.3.2",
- "doctrine": "^3.0.0",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.2",
- "eslint-visitor-keys": "^3.4.3",
- "espree": "^9.6.1",
- "esquery": "^1.4.2",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "globals": "^13.19.0",
- "graphemer": "^1.4.0",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "is-path-inside": "^3.0.3",
- "js-yaml": "^4.1.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.3",
- "strip-ansi": "^6.0.1",
- "text-table": "^0.2.0"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-config-prettier": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
- "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
- "dev": true,
- "bin": {
- "eslint-config-prettier": "bin/cli.js"
- },
- "peerDependencies": {
- "eslint": ">=7.0.0"
- }
- },
- "node_modules/eslint-plugin-prettier": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
- "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
- "dev": true,
- "dependencies": {
- "prettier-linter-helpers": "^1.0.0",
- "synckit": "^0.8.6"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint-plugin-prettier"
- },
- "peerDependencies": {
- "@types/eslint": ">=8.0.0",
- "eslint": ">=8.0.0",
- "eslint-config-prettier": "*",
- "prettier": ">=3.0.0"
- },
- "peerDependenciesMeta": {
- "@types/eslint": {
- "optional": true
- },
- "eslint-config-prettier": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-plugin-vue": {
- "version": "9.25.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.25.0.tgz",
- "integrity": "sha512-tDWlx14bVe6Bs+Nnh3IGrD+hb11kf2nukfm6jLsmJIhmiRQ1SUaksvwY9U5MvPB0pcrg0QK0xapQkfITs3RKOA==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.4.0",
- "globals": "^13.24.0",
- "natural-compare": "^1.4.0",
- "nth-check": "^2.1.1",
- "postcss-selector-parser": "^6.0.15",
- "semver": "^7.6.0",
- "vue-eslint-parser": "^9.4.2",
- "xml-name-validator": "^4.0.0"
- },
- "engines": {
- "node": "^14.17.0 || >=16.0.0"
- },
- "peerDependencies": {
- "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
- }
- },
- "node_modules/eslint-scope": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
- "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
- "dev": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/eslint/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/espree": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
- "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.9.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.4.1"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/esquery": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
- "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
- "dev": true,
- "dependencies": {
- "estraverse": "^5.1.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "dependencies": {
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estree-walker": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
- "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "node_modules/fast-diff": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
- "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
- "dev": true
- },
- "node_modules/fast-glob": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true
- },
- "node_modules/fastq": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
- "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
- "dev": true,
- "dependencies": {
- "flat-cache": "^3.0.4"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/flat-cache": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
- "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
- "dev": true,
- "dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.3",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/flatted": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
- "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
- "dev": true
- },
- "node_modules/follow-redirects": {
- "version": "1.15.6",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
- "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
- "node_modules/form-data": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
- "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/glob/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/glob/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/globals": {
- "version": "13.24.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
- "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
- "dev": true,
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "dependencies": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/graphemer": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
- "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
- "dev": true
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/he": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
- "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
- "dev": true,
- "bin": {
- "he": "bin/he"
- }
- },
- "node_modules/ignore": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
- "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "dev": true,
- "dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true
- },
- "node_modules/json-parse-even-better-errors": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz",
- "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==",
- "dev": true,
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true
- },
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
- "dependencies": {
- "json-buffer": "3.0.1"
- }
- },
- "node_modules/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true
- },
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true
- },
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/magic-string": {
- "version": "0.30.10",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
- "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.4.15"
- }
- },
- "node_modules/memorystream": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
- "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
- "dev": true,
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/minimatch": {
- "version": "9.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
- "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "node_modules/muggle-string": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
- "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
- "dev": true
- },
- "node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true
- },
- "node_modules/npm-normalize-package-bin": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz",
- "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==",
- "dev": true,
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/npm-run-all2": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-6.1.2.tgz",
- "integrity": "sha512-WwwnS8Ft+RpXve6T2EIEVpFLSqN+ORHRvgNk3H9N62SZXjmzKoRhMFg3I17TK3oMaAEr+XFbRirWS2Fn3BCPSg==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^6.2.1",
- "cross-spawn": "^7.0.3",
- "memorystream": "^0.3.1",
- "minimatch": "^9.0.0",
- "pidtree": "^0.6.0",
- "read-package-json-fast": "^3.0.2",
- "shell-quote": "^1.7.3"
- },
- "bin": {
- "npm-run-all": "bin/npm-run-all/index.js",
- "npm-run-all2": "bin/npm-run-all/index.js",
- "run-p": "bin/run-p/index.js",
- "run-s": "bin/run-s/index.js"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0",
- "npm": ">= 8"
- }
- },
- "node_modules/npm-run-all2/node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/nth-check": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
- "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
- "dev": true,
- "dependencies": {
- "boolbase": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/fb55/nth-check?sponsor=1"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/optionator": {
- "version": "0.9.4",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
- "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
- "dev": true,
- "dependencies": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.5"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "dependencies": {
- "callsites": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/path-browserify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
- "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
- "dev": true
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pidtree": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
- "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
- "dev": true,
- "bin": {
- "pidtree": "bin/pidtree.js"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.38",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.7",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.2.0"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss-selector-parser": {
- "version": "6.0.16",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
- "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
- "dev": true,
- "dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true,
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/prettier": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
- "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
- "dev": true,
- "bin": {
- "prettier": "bin/prettier.cjs"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
- }
- },
- "node_modules/prettier-linter-helpers": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
- "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
- "dev": true,
- "dependencies": {
- "fast-diff": "^1.1.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
- },
- "node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/read-package-json-fast": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz",
- "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==",
- "dev": true,
- "dependencies": {
- "json-parse-even-better-errors": "^3.0.0",
- "npm-normalize-package-bin": "^3.0.0"
- },
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/rollup": {
- "version": "4.17.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.0.tgz",
- "integrity": "sha512-wZJSn0WMtWrxhYKQRt5Z6GIXlziOoMDFmbHmRfL3v+sBTAshx2DBq1AfMArB7eIjF63r4ocn2ZTAyUptg/7kmQ==",
- "dev": true,
- "dependencies": {
- "@types/estree": "1.0.5"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.17.0",
- "@rollup/rollup-android-arm64": "4.17.0",
- "@rollup/rollup-darwin-arm64": "4.17.0",
- "@rollup/rollup-darwin-x64": "4.17.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.17.0",
- "@rollup/rollup-linux-arm-musleabihf": "4.17.0",
- "@rollup/rollup-linux-arm64-gnu": "4.17.0",
- "@rollup/rollup-linux-arm64-musl": "4.17.0",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.17.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.17.0",
- "@rollup/rollup-linux-s390x-gnu": "4.17.0",
- "@rollup/rollup-linux-x64-gnu": "4.17.0",
- "@rollup/rollup-linux-x64-musl": "4.17.0",
- "@rollup/rollup-win32-arm64-msvc": "4.17.0",
- "@rollup/rollup-win32-ia32-msvc": "4.17.0",
- "@rollup/rollup-win32-x64-msvc": "4.17.0",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/semver": {
- "version": "7.6.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
- "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shell-quote": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
- "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/synckit": {
- "version": "0.8.8",
- "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
- "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
- "dev": true,
- "dependencies": {
- "@pkgr/core": "^0.1.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/unts"
- }
- },
- "node_modules/text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/ts-api-utils": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
- "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
- "dev": true,
- "engines": {
- "node": ">=16"
- },
- "peerDependencies": {
- "typescript": ">=4.2.0"
- }
- },
- "node_modules/tslib": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
- "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
- "dev": true
- },
- "node_modules/type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "dependencies": {
- "prelude-ls": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/typescript": {
- "version": "5.4.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
- "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
- "devOptional": true,
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/undici-types": {
- "version": "5.26.5",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
- "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
- "dev": true
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
- },
- "node_modules/vite": {
- "version": "5.2.10",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz",
- "integrity": "sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==",
- "dev": true,
- "dependencies": {
- "esbuild": "^0.20.1",
- "postcss": "^8.4.38",
- "rollup": "^4.13.0"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || >=20.0.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/vue": {
- "version": "3.4.25",
- "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.25.tgz",
- "integrity": "sha512-HWyDqoBHMgav/OKiYA2ZQg+kjfMgLt/T0vg4cbIF7JbXAjDexRf5JRg+PWAfrAkSmTd2I8aPSXtooBFWHB98cg==",
- "dependencies": {
- "@vue/compiler-dom": "3.4.25",
- "@vue/compiler-sfc": "3.4.25",
- "@vue/runtime-dom": "3.4.25",
- "@vue/server-renderer": "3.4.25",
- "@vue/shared": "3.4.25"
- },
- "peerDependencies": {
- "typescript": "*"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/vue-eslint-parser": {
- "version": "9.4.2",
- "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz",
- "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==",
- "dev": true,
- "dependencies": {
- "debug": "^4.3.4",
- "eslint-scope": "^7.1.1",
- "eslint-visitor-keys": "^3.3.0",
- "espree": "^9.3.1",
- "esquery": "^1.4.0",
- "lodash": "^4.17.21",
- "semver": "^7.3.6"
- },
- "engines": {
- "node": "^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- },
- "peerDependencies": {
- "eslint": ">=6.0.0"
- }
- },
- "node_modules/vue-router": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.2.tgz",
- "integrity": "sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==",
- "dependencies": {
- "@vue/devtools-api": "^6.5.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/posva"
- },
- "peerDependencies": {
- "vue": "^3.2.0"
- }
- },
- "node_modules/vue-template-compiler": {
- "version": "2.7.16",
- "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
- "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==",
- "dev": true,
- "dependencies": {
- "de-indent": "^1.0.2",
- "he": "^1.2.0"
- }
- },
- "node_modules/vue-tsc": {
- "version": "2.0.14",
- "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.14.tgz",
- "integrity": "sha512-DgAO3U1cnCHOUO7yB35LENbkapeRsBZ7Ugq5hGz/QOHny0+1VQN8eSwSBjYbjLVPfvfw6EY7sNPjbuHHUhckcg==",
- "dev": true,
- "dependencies": {
- "@volar/typescript": "2.2.0-alpha.10",
- "@vue/language-core": "2.0.14",
- "semver": "^7.5.4"
- },
- "bin": {
- "vue-tsc": "bin/vue-tsc.js"
- },
- "peerDependencies": {
- "typescript": "*"
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/word-wrap": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
- "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
- "node_modules/xml-name-validator": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
- "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- }
- }
-}
diff --git a/frontend/package.json b/frontend/package.json
deleted file mode 100644
index 10a021d..0000000
--- a/frontend/package.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "name": "frontend",
- "version": "0.0.0",
- "private": true,
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "run-p type-check \"build-only {@}\" --",
- "preview": "vite preview",
- "build-only": "vite build",
- "type-check": "vue-tsc --build --force",
- "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
- "format": "prettier --write src/"
- },
- "dependencies": {
- "axios": "^1.6.8",
- "vue": "^3.4.21",
- "vue-router": "^4.3.0"
- },
- "devDependencies": {
- "@rushstack/eslint-patch": "^1.8.0",
- "@tsconfig/node20": "^20.1.4",
- "@types/node": "^20.12.5",
- "@vitejs/plugin-vue": "^5.0.4",
- "@vue/eslint-config-prettier": "^9.0.0",
- "@vue/eslint-config-typescript": "^13.0.0",
- "@vue/tsconfig": "^0.5.1",
- "eslint": "^8.57.0",
- "eslint-plugin-vue": "^9.23.0",
- "npm-run-all2": "^6.1.2",
- "prettier": "^3.2.5",
- "typescript": "~5.4.0",
- "vite": "^5.2.8",
- "vue-tsc": "^2.0.11"
- }
-}
diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico
deleted file mode 100644
index df36fcfb72584e00488330b560ebcf34a41c64c2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 4286
zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj
zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56
zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy
zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei
z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX
zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm
zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp=
zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8
zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO
z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3
z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD
zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6
z={Xwx{T%b6i9IjI)Ls)S{-*mq<@~R{?$}ZKjf;^k75i_}(2MXt}^SEBVg7AI@28
zo_uPg2V)_e-`2Ois=PYoe%9u*n9({PFR)OnHJPi{dNx>KxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
deleted file mode 100644
index ad56b70..0000000
--- a/frontend/src/App.vue
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
diff --git a/frontend/src/api/api.ts b/frontend/src/api/api.ts
deleted file mode 100644
index 7ec0039..0000000
--- a/frontend/src/api/api.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import axios from "axios";
-import type { AxiosResponse } from "axios";
-import type { DownloadResponse, MediaItemResponse } from "@/api/interfaces";
-
-const BASE_URL = "http://localhost:8000/api";
-
-const api = axios.create({
- baseURL: BASE_URL,
-});
-
-async function get(url: string): Promise> {
- return api.get(url);
-}
-
-async function post(url: string, data: any): Promise> {
- return api.post(url, data);
-}
-
-export default function search(
- query: string,
- type: string
-): Promise> {
- return get(`/search?search_terms=${query}&type=${type}`);
-}
-
-export async function getEpisodesInfo(
- mediaId: number,
- mediaSlug: string,
- mediaType: string
-): Promise {
- const url = `/search/get_episodes_info?media_id=${mediaId}&media_slug=${mediaSlug}&type_media=${mediaType}`;
- return fetch(`${BASE_URL}${url}`, {
- method: "GET",
- headers: {
- "Content-Type": "text/event-stream",
- },
- });
-}
-
-export async function getPreview(
- mediaId: number,
- mediaSlug: string,
- mediaType: string
-): Promise> {
- const url = `/search/get_preview?media_id=${mediaId}&media_slug=${mediaSlug}&type_media=${mediaType}`;
- return get(url);
-}
-
-async function downloadMedia(
- mediaId: number,
- mediaSlug: string,
- mediaType: string,
- downloadId?: number,
- tvSeriesEpisodeId?: number
-): Promise> {
- const url = `/download/`;
- const data = {
- media_id: mediaId,
- media_slug: mediaSlug,
- type_media: mediaType,
- download_id: downloadId,
- tv_series_episode_id: tvSeriesEpisodeId,
- };
- return post(url, data);
-}
-
-export const downloadFilm = (mediaId: number, mediaSlug: string) =>
- downloadMedia(mediaId, mediaSlug, "MOVIE");
-export const downloadTvSeries = (
- mediaId: number,
- mediaSlug: string,
- downloadId: number,
- tvSeriesEpisodeId?: number
-) => downloadMedia(mediaId, mediaSlug, "TV", downloadId, tvSeriesEpisodeId);
-export const downloadAnimeFilm = (mediaId: number, mediaSlug: string) =>
- downloadMedia(mediaId, mediaSlug, "OVA");
-export const downloadAnimeSeries = (
- mediaId: number,
- mediaSlug: string,
- downloadId: number
-) => downloadMedia(mediaId, mediaSlug, "TV_ANIME", downloadId);
diff --git a/frontend/src/api/interfaces.ts b/frontend/src/api/interfaces.ts
deleted file mode 100644
index d33f703..0000000
--- a/frontend/src/api/interfaces.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-interface Image {
- imageable_id: number;
- imageable_type: string;
- filename: string;
- type: string;
- original_url_field: string;
-}
-
-export interface MediaItem {
- id: number;
- slug: string;
- name: string;
- type: string;
- score: string;
- sub_ita: number;
- last_air_date: string;
- seasons_count: number;
- images: Image[];
- comment: string;
- plot: string;
-}
-
-export interface MediaItemResponse {
- media: MediaItem[];
-}
-
-export interface Episode {
- id: number;
- anime_id: number;
- user_id: number | null;
- number: string;
- created_at: string;
- link: string;
- visite: number;
- hidden: number;
- public: number;
- scws_id: number;
- file_name: string;
- tg_post: number;
- episode_id: number;
- episode_total: number;
- name: string; // TV Show exclusive
- plot: string; // TV Show exclusive
- duration: number; // TV Show exclusive
- season_id: number; // TV Show exclusive
- created_by: any; // TV Show exclusive
- updated_at: string; // TV Show exclusive
- season_index: number; // TV Show exclusive
-}
-
-export interface Season {
- [key: string]: {
- [key: string]: Episode;
- };
-}
-
-export interface SeasonResponse {
- episodes: Season;
-}
-
-export interface DownloadResponse {
- error: string;
- message: string;
-}
\ No newline at end of file
diff --git a/frontend/src/api/utils.ts b/frontend/src/api/utils.ts
deleted file mode 100644
index 4432fdd..0000000
--- a/frontend/src/api/utils.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import {downloadAnimeFilm, downloadAnimeSeries, downloadFilm, downloadTvSeries} from "@/api/api";
-import type {DownloadResponse, Episode, MediaItem, Season} from "@/api/interfaces";
-
-export const handleTVDownload = async (tvShowEpisodes: any[], item: MediaItem) => {
- alertDownload();
- for (const season of tvShowEpisodes) {
- const i = tvShowEpisodes.indexOf(season);
- const res = (await downloadTvSeries(item.id, item.slug, i + 1)).data;
- handleDownloadError(res);
- }
-};
-
-export const handleTVEpisodesDownload = async (episodes: Episode[], item: MediaItem) => {
- alertDownload();
- for (const episode of episodes) {
- const i = episodes.indexOf(episode);
- const res = (await downloadTvSeries(item.id, item.slug, episode.season_index + 1, i)).data;
- handleDownloadError(res);
- }
-}
-
-export const handleMovieDownload = async (item: MediaItem) => {
- alertDownload();
- const res = (await downloadFilm(item.id, item.slug)).data;
- handleDownloadError(res);
-};
-
-export const handleTVAnimeDownload = async (episodeCount: number, item: MediaItem) => {
- alertDownload();
- for (let i = 0; i < episodeCount; i++) {
- const res = (await downloadAnimeSeries(item.id, item.slug, i)).data;
- handleDownloadError(res);
- }
-};
-
-export const handleTvAnimeEpisodesDownload = async (episodes: Episode[], item: MediaItem) => {
- alertDownload();
- for (const episode of episodes) {
- const res = (await downloadAnimeSeries(item.id, item.slug, episode.episode_id)).data;
- handleDownloadError(res);
- }
-
-}
-
-export const handleOVADownload = async (item: MediaItem) => {
- alertDownload();
- const res = (await downloadAnimeFilm(item.id, item.slug)).data;
- handleDownloadError(res);
-};
-
-const handleDownloadError = (res: DownloadResponse) => {
- if (res.error) {
- throw new Error(`${res.error} - ${res.message}`);
- }
-};
-
-export const alertDownload = (message?: any) => {
- if (message) {
- alert(message)
- return;
- }
- alert('Il downlaod è iniziato, il file sarà disponibile tra qualche minuto nella cartella \'Video\' del progetto...')
-}
\ No newline at end of file
diff --git a/frontend/src/assets/base.css b/frontend/src/assets/base.css
deleted file mode 100644
index 8816868..0000000
--- a/frontend/src/assets/base.css
+++ /dev/null
@@ -1,86 +0,0 @@
-/* color palette from */
-:root {
- --vt-c-white: #ffffff;
- --vt-c-white-soft: #f8f8f8;
- --vt-c-white-mute: #f2f2f2;
-
- --vt-c-black: #181818;
- --vt-c-black-soft: #222222;
- --vt-c-black-mute: #282828;
-
- --vt-c-indigo: #2c3e50;
-
- --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
- --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
- --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
- --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
-
- --vt-c-text-light-1: var(--vt-c-indigo);
- --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
- --vt-c-text-dark-1: var(--vt-c-white);
- --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
-}
-
-/* semantic color variables for this project */
-:root {
- --color-background: var(--vt-c-white);
- --color-background-soft: var(--vt-c-white-soft);
- --color-background-mute: var(--vt-c-white-mute);
-
- --color-border: var(--vt-c-divider-light-2);
- --color-border-hover: var(--vt-c-divider-light-1);
-
- --color-heading: var(--vt-c-text-light-1);
- --color-text: var(--vt-c-text-light-1);
-
- --section-gap: 160px;
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --color-background: var(--vt-c-black);
- --color-background-soft: var(--vt-c-black-soft);
- --color-background-mute: var(--vt-c-black-mute);
-
- --color-border: var(--vt-c-divider-dark-2);
- --color-border-hover: var(--vt-c-divider-dark-1);
-
- --color-heading: var(--vt-c-text-dark-1);
- --color-text: var(--vt-c-text-dark-2);
- }
-}
-
-*,
-*::before,
-*::after {
- box-sizing: border-box;
- margin: 0;
- font-weight: normal;
-}
-
-body {
- min-height: 100vh;
- color: var(--color-text);
- background: var(--color-background);
- transition:
- color 0.5s,
- background-color 0.5s;
- line-height: 1.6;
- font-family:
- Inter,
- -apple-system,
- BlinkMacSystemFont,
- 'Segoe UI',
- Roboto,
- Oxygen,
- Ubuntu,
- Cantarell,
- 'Fira Sans',
- 'Droid Sans',
- 'Helvetica Neue',
- sans-serif;
- font-size: 15px;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
diff --git a/frontend/src/assets/logo.svg b/frontend/src/assets/logo.svg
deleted file mode 100644
index 7565660..0000000
--- a/frontend/src/assets/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/frontend/src/assets/main.css b/frontend/src/assets/main.css
deleted file mode 100644
index 36fb845..0000000
--- a/frontend/src/assets/main.css
+++ /dev/null
@@ -1,35 +0,0 @@
-@import './base.css';
-
-#app {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- font-weight: normal;
-}
-
-a,
-.green {
- text-decoration: none;
- color: hsla(160, 100%, 37%, 1);
- transition: 0.4s;
- padding: 3px;
-}
-
-@media (hover: hover) {
- a:hover {
- background-color: hsla(160, 100%, 37%, 0.2);
- }
-}
-
-@media (min-width: 1024px) {
- body {
- display: flex;
- place-items: center;
- }
-
- #app {
- display: grid;
- grid-template-columns: 1fr 1fr;
- padding: 0 2rem;
- }
-}
diff --git a/frontend/src/components/Card.vue b/frontend/src/components/Card.vue
deleted file mode 100644
index 9817f43..0000000
--- a/frontend/src/components/Card.vue
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
-
![]()
-
- {{ item.name.slice(0, 25) + (item.name.length > 24 ? '...' : '') }}
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/Toggle.vue b/frontend/src/components/Toggle.vue
deleted file mode 100644
index 1f31799..0000000
--- a/frontend/src/components/Toggle.vue
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
- Film/Serie TV
-
- Anime
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
deleted file mode 100644
index 5a5dbdb..0000000
--- a/frontend/src/main.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import './assets/main.css'
-
-import { createApp } from 'vue'
-import App from './App.vue'
-import router from './router'
-
-const app = createApp(App)
-
-app.use(router)
-
-app.mount('#app')
diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts
deleted file mode 100644
index fbbbafb..0000000
--- a/frontend/src/router/index.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { createRouter, createWebHistory } from 'vue-router'
-import HomeView from '../views/HomeView.vue'
-import Details from "../views/Details.vue";
-
-const router = createRouter({
- history: createWebHistory(import.meta.env.BASE_URL),
- routes: [
- {
- path: '/',
- name: 'home',
- component: HomeView
- },
- {
- path: '/details:item:imageUrl',
- name: 'details',
- component: Details,
- props: route => {
- let item;
- try {
- item = JSON.parse(route.params.item);
- } catch (error) {
- item = {}; // default value
- }
- return { item: item, imageUrl: route.params.imageUrl };
- },
- }
- ]
-})
-
-export default router
diff --git a/frontend/src/views/Details.vue b/frontend/src/views/Details.vue
deleted file mode 100644
index 5880730..0000000
--- a/frontend/src/views/Details.vue
+++ /dev/null
@@ -1,335 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
Non ci sono episodi...
-
-
-
Episodio {{ episode.number }}
-
-
-
Stagione {{ index + 1 }}
-
-
-
-
- Episodio {{ episode.number }} -
- {{episode.name.slice(0, 40) + (episode.name.length > 39 ? '...' : '')}}
-
-
-
-
-
-
-
-
-
-
Questo è un {{item.type}} (QUESTO TESTO E' A SCOPO DI TEST)
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/views/HomeView.vue b/frontend/src/views/HomeView.vue
deleted file mode 100644
index 5919c7e..0000000
--- a/frontend/src/views/HomeView.vue
+++ /dev/null
@@ -1,176 +0,0 @@
-
-
-
-
-
-
-
Nessun risultato trovato
-
-
-
-
\ No newline at end of file
diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json
deleted file mode 100644
index e14c754..0000000
--- a/frontend/tsconfig.app.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "extends": "@vue/tsconfig/tsconfig.dom.json",
- "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
- "exclude": ["src/**/__tests__/*"],
- "compilerOptions": {
- "composite": true,
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
-
- "baseUrl": ".",
- "paths": {
- "@/*": ["./src/*"]
- }
- }
-}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
deleted file mode 100644
index 66b5e57..0000000
--- a/frontend/tsconfig.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "files": [],
- "references": [
- {
- "path": "./tsconfig.node.json"
- },
- {
- "path": "./tsconfig.app.json"
- }
- ]
-}
diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json
deleted file mode 100644
index f094063..0000000
--- a/frontend/tsconfig.node.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "extends": "@tsconfig/node20/tsconfig.json",
- "include": [
- "vite.config.*",
- "vitest.config.*",
- "cypress.config.*",
- "nightwatch.conf.*",
- "playwright.config.*"
- ],
- "compilerOptions": {
- "composite": true,
- "noEmit": true,
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
-
- "module": "ESNext",
- "moduleResolution": "Bundler",
- "types": ["node"]
- }
-}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
deleted file mode 100644
index 5c45e1d..0000000
--- a/frontend/vite.config.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { fileURLToPath, URL } from 'node:url'
-
-import { defineConfig } from 'vite'
-import vue from '@vitejs/plugin-vue'
-
-// https://vitejs.dev/config/
-export default defineConfig({
- plugins: [
- vue(),
- ],
- resolve: {
- alias: {
- '@': fileURLToPath(new URL('./src', import.meta.url))
- }
- }
-})
diff --git a/kill_gui.sh b/kill_gui.sh
deleted file mode 100755
index c7fac45..0000000
--- a/kill_gui.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-# Trova i processi che utilizzano la porta 8000
-PROCESSES=$(lsof -i :8000 | awk 'NR!=1 {print $2}')
-
-# Termina i processi trovati
-if [ -n "$PROCESSES" ]; then
- echo "Terminating processes using port 8000:"
- for PID in $PROCESSES; do
- echo "Killing process with PID: $PID"
- kill -9 $PID
- done
-else
- echo "No processes found using port 8000"
-fi
-
-# Trova i processi che utilizzano la porta 5173
-PROCESSES=$(lsof -i :5173 | awk 'NR!=1 {print $2}')
-
-# Termina i processi trovati
-if [ -n "$PROCESSES" ]; then
- echo "Terminating processes using port 5173:"
- for PID in $PROCESSES; do
- echo "Killing process with PID: $PID"
- kill -9 $PID
- done
-else
- echo "No processes found using port 5173"
-fi
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index d471fcb..21218f8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,11 +1,4 @@
bs4
tqdm
rich
-unidecode
-ffmpeg-python
-pycryptodome
-m3u8
-lxml
-django==4.2.11
-djangorestframework==3.15.1
-django-cors-headers==4.3.1
\ No newline at end of file
+unidecode
\ No newline at end of file
diff --git a/start_gui.sh b/start_gui.sh
deleted file mode 100755
index e339262..0000000
--- a/start_gui.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-# Installa i pacchetti Python
-echo "Installazione dei pacchetti Python..."
-pip install -r requirements.txt
-
-# Installa i pacchetti npm
-echo "Installazione dei pacchetti npm..."
-cd frontend
-npm install
-cd ..
-
-# Avvia il backend Django
-echo "Avvio del backend Django..."
-python3.11 api/manage.py runserver &
-
-# Avvia il frontend Vue.js con Vite
-echo "Avvio del frontend Vue.js con Vite..."
-cd frontend
-npm run dev &
-
-# Attendi l'esecuzione dei processi
-wait
\ No newline at end of file
From 2960b810cd9089978fa72a6cf0c9069f14fac784 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Sat, 1 Jun 2024 14:20:50 +0200
Subject: [PATCH 03/13] Fix shorter video and small bar, remove ctrl+c.
---
Src/Api/Animeunity/Core/Vix_player/player.py | 4 +-
.../Core/Vix_player/player.py | 3 +-
Src/Api/Streamingcommunity/costant.py | 5 +-
Src/Lib/FFmpeg/capture.py | 4 +
Src/Lib/FFmpeg/command.py | 94 ++++++++++++++-----
Src/Lib/FFmpeg/util.py | 28 +++++-
Src/Lib/Hls/downloader.py | 37 +++++---
Src/Lib/Hls/segments.py | 34 ++-----
Src/Lib/M3U8/parser.py | 48 ++++++----
Src/Lib/Request/my_requests.py | 6 +-
Src/Util/os.py | 17 +++-
config.json | 5 +-
run.py | 64 ++++++-------
13 files changed, 222 insertions(+), 127 deletions(-)
diff --git a/Src/Api/Animeunity/Core/Vix_player/player.py b/Src/Api/Animeunity/Core/Vix_player/player.py
index 9fad807..bcac59a 100644
--- a/Src/Api/Animeunity/Core/Vix_player/player.py
+++ b/Src/Api/Animeunity/Core/Vix_player/player.py
@@ -1,5 +1,6 @@
# 01.03.24
+import sys
import logging
from urllib.parse import urljoin, urlparse, parse_qs, urlencode, urlunparse
@@ -11,6 +12,7 @@ from bs4 import BeautifulSoup
# Internal utilities
from Src.Util.headers import get_headers
+from Src.Util.console import console
from Src.Util._jsonConfig import config_manager
@@ -204,4 +206,4 @@ class VideoSource:
new_url = m._replace(query=new_query) # Replace the old query string with the new one
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
- return final_url
\ No newline at end of file
+ return final_url
diff --git a/Src/Api/Streamingcommunity/Core/Vix_player/player.py b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
index 831e216..e72e7e0 100644
--- a/Src/Api/Streamingcommunity/Core/Vix_player/player.py
+++ b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
@@ -202,7 +202,6 @@ class VideoSource:
logging.error(f"Error getting content: {e}")
raise
-
def get_playlist(self) -> str:
"""
Get playlist.
@@ -240,4 +239,4 @@ class VideoSource:
new_url = m._replace(query=new_query) # Replace the old query string with the new one
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
- return final_url
\ No newline at end of file
+ return final_url
diff --git a/Src/Api/Streamingcommunity/costant.py b/Src/Api/Streamingcommunity/costant.py
index e1e8653..8ac2f97 100644
--- a/Src/Api/Streamingcommunity/costant.py
+++ b/Src/Api/Streamingcommunity/costant.py
@@ -4,4 +4,7 @@ STREAMING_FOLDER = "streamingcommunity"
MOVIE_FOLDER = "Movie"
SERIES_FOLDER = "Serie"
-SERVER_IP = ['162.19.231.20', '162.19.255.224', '162.19.254.232', '162.19.254.230', '51.195.107.230', '162.19.255.36', '162.19.228.128', '51.195.107.7', '162.19.253.242', '141.95.0.248', '57.129.4.77', '57.129.7.85']
\ No newline at end of file
+SERVER_IP = ['162.19.255.224', '162.19.255.223', '162.19.254.244', '162.19.254.232', '162.19.254.230',
+ '162.19.253.242', '162.19.249.48', '162.19.245.142', '162.19.231.20', '162.19.229.177',
+ '162.19.228.128', '162.19.228.127', '162.19.228.105', '141.95.1.32', '141.95.1.196',
+ '141.95.1.102', '141.95.0.50', '141.95.0.248', '135.125.237.84', '135.125.233.236']
\ No newline at end of file
diff --git a/Src/Lib/FFmpeg/capture.py b/Src/Lib/FFmpeg/capture.py
index fe4ddbd..561820e 100644
--- a/Src/Lib/FFmpeg/capture.py
+++ b/Src/Lib/FFmpeg/capture.py
@@ -40,6 +40,10 @@ def capture_output(process: subprocess.Popen, description: str) -> None:
logging.info(f"FFMPEG line: {line}")
+ # Capture only error
+ if "rror" in str(line):
+ console.log(f"[red]FFMPEG: {str(line).strip()}")
+
# Check if termination is requested
if terminate_flag.is_set():
break
diff --git a/Src/Lib/FFmpeg/command.py b/Src/Lib/FFmpeg/command.py
index af2f57b..f3b85c1 100644
--- a/Src/Lib/FFmpeg/command.py
+++ b/Src/Lib/FFmpeg/command.py
@@ -19,14 +19,18 @@ except: pass
from Src.Util._jsonConfig import config_manager
from Src.Util.os import check_file_existence, suppress_output
from Src.Util.console import console
-from .util import has_audio_stream, need_to_force_to_ts, check_ffmpeg_input
+from .util import has_audio_stream, need_to_force_to_ts, check_ffmpeg_input, check_duration_v_a
from .capture import capture_ffmpeg_real_time
+from ..M3U8.parser import M3U8_Codec
# Config
DEBUG_MODE = config_manager.get_bool("DEFAULT", "debug")
DEBUG_FFMPEG = "debug" if DEBUG_MODE else "error"
-USE_CODECS = config_manager.get_bool("M3U8_CONVERSION", "use_codec")
+USE_CODEC = config_manager.get_bool("M3U8_CONVERSION", "use_codec")
+USE_VCODEC = config_manager.get_bool("M3U8_CONVERSION", "use_vcodec")
+USE_ACODEC = config_manager.get_bool("M3U8_CONVERSION", "use_acodec")
+USE_BITRATE = config_manager.get_bool("M3U8_CONVERSION", "use_bitrate")
USE_GPU = config_manager.get_bool("M3U8_CONVERSION", "use_gpu")
FFMPEG_DEFAULT_PRESET = config_manager.get("M3U8_CONVERSION", "default_preset")
CHECK_OUTPUT_CONVERSION = config_manager.get_bool("M3U8_CONVERSION", "check_output_after_ffmpeg")
@@ -263,7 +267,7 @@ def __transcode_with_subtitles(video: str, subtitles_list: List[Dict[str, str]],
# --> v 1.1 (new)
-def join_video(video_path: str, out_path: str, vcodec: str = None, acodec: str = None, bitrate: str = None):
+def join_video(video_path: str, out_path: str, codec: M3U8_Codec = None):
"""
Joins single ts video file to mp4
@@ -281,12 +285,12 @@ def join_video(video_path: str, out_path: str, vcodec: str = None, acodec: str =
logging.error("Missing input video for ffmpeg conversion.")
sys.exit(0)
-
# Start command
ffmpeg_cmd = ['ffmpeg']
# Enabled the use of gpu
- ffmpeg_cmd.extend(['-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda'])
+ if USE_GPU:
+ ffmpeg_cmd.extend(['-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda'])
# Add mpegts to force to detect input file as ts file
if need_to_force_to_ts(video_path):
@@ -294,15 +298,30 @@ def join_video(video_path: str, out_path: str, vcodec: str = None, acodec: str =
ffmpeg_cmd.extend(['-f', 'mpegts'])
vcodec = "libx264"
-
# Insert input video path
ffmpeg_cmd.extend(['-i', video_path])
# Add output args
- if USE_CODECS:
- if vcodec: ffmpeg_cmd.extend(['-c:v', vcodec])
- if acodec: ffmpeg_cmd.extend(['-c:a', acodec])
- if bitrate: ffmpeg_cmd.extend(['-b:a', str(bitrate)])
+ if USE_CODEC:
+ if USE_VCODEC:
+ if codec.video_codec_name:
+ if not USE_GPU:
+ ffmpeg_cmd.extend(['-c:v', codec.video_codec_name])
+ else:
+ ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
+ else:
+ console.log("[red]Cant find vcodec for 'join_audios'")
+
+ if USE_ACODEC:
+ if codec.audio_codec_name:
+ ffmpeg_cmd.extend(['-c:a', codec.audio_codec_name])
+ else:
+ console.log("[red]Cant find acodec for 'join_audios'")
+
+ if USE_BITRATE:
+ ffmpeg_cmd.extend(['-b:v', f'{codec.video_bitrate // 1000}k'])
+ ffmpeg_cmd.extend(['-b:a', f'{codec.audio_bitrate // 1000}k'])
+
else:
ffmpeg_cmd.extend(['-c', 'copy'])
@@ -312,12 +331,10 @@ def join_video(video_path: str, out_path: str, vcodec: str = None, acodec: str =
else:
ffmpeg_cmd.extend(['-preset', 'fast'])
-
# Overwrite
ffmpeg_cmd += [out_path, "-y"]
logging.info(f"FFmpeg command: {ffmpeg_cmd}")
-
# Run join
if DEBUG_MODE:
subprocess.run(ffmpeg_cmd, check=True)
@@ -333,8 +350,6 @@ def join_video(video_path: str, out_path: str, vcodec: str = None, acodec: str =
capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join video")
print()
-
-
# Check file output
if CHECK_OUTPUT_CONVERSION:
console.log("[red]Check output ffmpeg")
@@ -347,7 +362,7 @@ def join_video(video_path: str, out_path: str, vcodec: str = None, acodec: str =
sys.exit(0)
-def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: str):
+def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: str, codec: M3U8_Codec = None):
"""
Joins audio tracks with a video file using FFmpeg.
@@ -362,9 +377,17 @@ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: s
logging.error("Missing input video for ffmpeg conversion.")
sys.exit(0)
+ video_audio_same_duration = check_duration_v_a(video_path, audio_tracks[0].get('path'))
# Start command
- ffmpeg_cmd = ['ffmpeg', '-i', video_path]
+ ffmpeg_cmd = ['ffmpeg']
+
+ # Enabled the use of gpu
+ if USE_GPU:
+ ffmpeg_cmd.extend(['-hwaccel', 'cuda', '-hwaccel_output_format', 'cuda'])
+
+ # Insert input video path
+ ffmpeg_cmd.extend(['-i', video_path])
# Add audio tracks as input
for i, audio_track in enumerate(audio_tracks):
@@ -373,7 +396,6 @@ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: s
else:
logging.error(f"Skip audio join: {audio_track.get('path')} dont exist")
-
# Map the video and audio streams
ffmpeg_cmd.append('-map')
ffmpeg_cmd.append('0:v') # Map video stream from the first input (video_path)
@@ -382,18 +404,45 @@ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: s
ffmpeg_cmd.append('-map')
ffmpeg_cmd.append(f'{i}:a') # Map audio streams from subsequent inputs
-
# Add output args
- if USE_CODECS:
- ffmpeg_cmd.extend(['-c:v', 'copy', '-c:a', 'copy'])
+ if USE_CODEC:
+ if USE_VCODEC:
+ if codec.video_codec_name:
+ if not USE_GPU:
+ ffmpeg_cmd.extend(['-c:v', codec.video_codec_name])
+ else:
+ ffmpeg_cmd.extend(['-c:v', 'h264_nvenc'])
+ else:
+ console.log("[red]Cant find vcodec for 'join_audios'")
+
+ if USE_ACODEC:
+ if codec.audio_codec_name:
+ ffmpeg_cmd.extend(['-c:a', codec.audio_codec_name])
+ else:
+ console.log("[red]Cant find acodec for 'join_audios'")
+
+ if USE_BITRATE:
+ ffmpeg_cmd.extend(['-b:v', f'{codec.video_bitrate // 1000}k'])
+ ffmpeg_cmd.extend(['-b:a', f'{codec.audio_bitrate // 1000}k'])
+
else:
ffmpeg_cmd.extend(['-c', 'copy'])
+ # Ultrafast preset always or fast for gpu
+ if not USE_GPU:
+ ffmpeg_cmd.extend(['-preset', FFMPEG_DEFAULT_PRESET])
+ else:
+ ffmpeg_cmd.extend(['-preset', 'fast'])
+
+ # Use shortest input path for video and audios
+ if not video_audio_same_duration:
+ console.log("[red]Use shortest input.")
+ ffmpeg_cmd.extend(['-shortest', '-strict', 'experimental'])
+
# Overwrite
ffmpeg_cmd += [out_path, "-y"]
logging.info(f"FFmpeg command: {ffmpeg_cmd}")
-
# Run join
if DEBUG_MODE:
subprocess.run(ffmpeg_cmd, check=True)
@@ -409,7 +458,6 @@ def join_audios(video_path: str, audio_tracks: List[Dict[str, str]], out_path: s
capture_ffmpeg_real_time(ffmpeg_cmd, "[cyan]Join audio")
print()
-
# Check file output
if CHECK_OUTPUT_CONVERSION:
console.log("[red]Check output ffmpeg")
@@ -456,7 +504,7 @@ def join_subtitle(video_path: str, subtitles_list: List[Dict[str, str]], out_pat
ffmpeg_cmd += ["-metadata:s:s:{}".format(idx), "title={}".format(subtitle['name'])]
# Add output args
- if USE_CODECS:
+ if USE_CODEC:
ffmpeg_cmd.extend(['-c:v', 'copy', '-c:a', 'copy', '-c:s', 'mov_text'])
else:
ffmpeg_cmd.extend(['-c', 'copy', '-c:s', 'mov_text'])
diff --git a/Src/Lib/FFmpeg/util.py b/Src/Lib/FFmpeg/util.py
index 4e03244..10ef22c 100644
--- a/Src/Lib/FFmpeg/util.py
+++ b/Src/Lib/FFmpeg/util.py
@@ -92,7 +92,7 @@ def format_duration(seconds: float) -> Tuple[int, int, int]:
return int(hours), int(minutes), int(seconds)
-def print_duration_table(file_path: str) -> None:
+def print_duration_table(file_path: str, show = True) -> None:
"""
Print duration of a video file in hours, minutes, and seconds.
@@ -104,7 +104,10 @@ def print_duration_table(file_path: str) -> None:
if video_duration is not None:
hours, minutes, seconds = format_duration(video_duration)
- console.log(f"[cyan]Duration for [white]([green]{os.path.basename(file_path)}[white]): [yellow]{int(hours)}[red]h [yellow]{int(minutes)}[red]m [yellow]{int(seconds)}[red]s")
+ if show:
+ console.print(f"[cyan]Duration for [white]([green]{os.path.basename(file_path)}[white]): [yellow]{int(hours)}[red]h [yellow]{int(minutes)}[red]m [yellow]{int(seconds)}[red]s")
+ else:
+ return f"[yellow]{int(hours)}[red]h [yellow]{int(minutes)}[red]m [yellow]{int(seconds)}[red]s"
def get_ffprobe_info(file_path):
@@ -210,3 +213,24 @@ def check_ffmpeg_input(input_file):
except Exception as e:
logging.error(f"An unexpected error occurred: {e}")
return False
+
+def check_duration_v_a(video_path, audio_path):
+ """
+ Check if the duration of the video and audio matches.
+
+ Args:
+ - video_path (str): Path to the video file.
+ - audio_path (str): Path to the audio file.
+
+ Returns:
+ - bool: True if the duration of the video and audio matches, False otherwise.
+ """
+
+ # Ottieni la durata del video
+ video_duration = get_video_duration(video_path)
+
+ # Ottieni la durata dell'audio
+ audio_duration = get_video_duration(audio_path)
+
+ # Verifica se le durate corrispondono
+ return video_duration == audio_duration
\ No newline at end of file
diff --git a/Src/Lib/Hls/downloader.py b/Src/Lib/Hls/downloader.py
index a3fea2c..9ef3ff3 100644
--- a/Src/Lib/Hls/downloader.py
+++ b/Src/Lib/Hls/downloader.py
@@ -178,7 +178,7 @@ class Downloader():
# Check if there is some audios, else disable download
if self.list_available_audio != None:
- console.log(f"[cyan]Find audios [white]=> [red]{[obj_audio.get('language') for obj_audio in self.list_available_audio]}")
+ console.print(f"[cyan]Find audios [white]=> [red]{[obj_audio.get('language') for obj_audio in self.list_available_audio]}")
else:
console.log("[red]Cant find a list of audios")
@@ -191,7 +191,7 @@ class Downloader():
# Check if there is some subtitles, else disable download
if self.list_available_subtitles != None:
- console.log(f"[cyan]Find subtitles [white]=> [red]{[obj_sub.get('language') for obj_sub in self.list_available_subtitles]}")
+ console.print(f"[cyan]Find subtitles [white]=> [red]{[obj_sub.get('language') for obj_sub in self.list_available_subtitles]}")
else:
console.log("[red]Cant find a list of audios")
@@ -208,7 +208,7 @@ class Downloader():
logging.info(f"M3U8 index select: {self.m3u8_index}, with resolution: {video_res}")
# Get URI of the best quality and codecs parameters
- console.log(f"[cyan]Find resolution [white]=> [red]{sorted(list_available_resolution, reverse=True)}")
+ console.print(f"[cyan]Find resolution [white]=> [red]{sorted(list_available_resolution, reverse=True)}")
# Fix URL if it is not complete with http:\\site_name.domain\...
if "http" not in self.m3u8_index:
@@ -219,7 +219,7 @@ class Downloader():
# Check if a valid HTTPS URL is obtained
if self.m3u8_index is not None and "https" in self.m3u8_index:
- console.log(f"[cyan]Found m3u8 index [white]=> [red]{self.m3u8_index}")
+ console.print(f"[cyan]Found m3u8 index [white]=> [red]{self.m3u8_index}")
else:
logging.error("[download_m3u8] Can't find a valid m3u8 index")
raise
@@ -229,7 +229,8 @@ class Downloader():
logging.info(f"Find codec: {self.codec}")
if self.codec is not None:
- console.log(f"[cyan]Find codec [white]=> ([green]'v'[white]: [yellow]{self.codec.video_codec_name}[white], [green]'a'[white]: [yellow]{self.codec.audio_codec_name}[white], [green]'b'[white]: [yellow]{self.codec.bandwidth})")
+ console.print(f"[cyan]Find codec [white]=> ([green]'v'[white]: [yellow]{self.codec.video_codec_name}[white] ([green]b[white]: [yellow]{self.codec.video_bitrate // 1000}k[white]), [green]'a'[white]: [yellow]{self.codec.audio_codec_name}[white] ([green]b[white]: [yellow]{self.codec.audio_bitrate // 1000}k[white]))")
+
def __donwload_video__(self, server_ip: list = None):
"""
@@ -263,6 +264,9 @@ class Downloader():
# Download the video segments
video_m3u8.download_streams(f"{Colors.MAGENTA}video")
+ # Get time of output file
+ print_duration_table(os.path.join(full_path_video, "0.ts"))
+
else:
console.log("[cyan]Video [red]already exists.")
@@ -309,6 +313,9 @@ class Downloader():
# Download the audio segments
audio_m3u8.download_streams(f"{Colors.MAGENTA}audio {Colors.RED}{obj_audio.get('language')}")
+ # Get time of output file
+ print_duration_table(os.path.join(full_path_audio, "0.ts"))
+
else:
console.log(f"[cyan]Audio [white]([green]{obj_audio.get('language')}[white]) [red]already exists.")
@@ -373,14 +380,14 @@ class Downloader():
)
# Initiate the download of the subtitle content
- console.log(f"[cyan]Downloading subtitle: [red]{sub_language.lower()}")
+ console.print(f"[cyan]Downloading subtitle: [red]{sub_language.lower()}")
futures.append(executor.submit(self.__save_subtitle_content, m3u8_sub_parser.subtitle[-1], sub_full_path))
# Wait for all downloads to finish
for future in futures:
future.result()
- def __join_video__(self, vcodec = 'copy') -> str:
+ def __join_video__(self) -> str:
"""
Join downloaded video segments into a single video file.
@@ -397,10 +404,9 @@ class Downloader():
join_video(
video_path = self.downloaded_video[0].get('path'),
out_path = path_join_video,
- vcodec = vcodec
+ codec = self.codec
)
- print_duration_table(path_join_video)
return path_join_video
def __join_video_audio__(self) -> str:
@@ -420,10 +426,10 @@ class Downloader():
join_audios(
video_path = self.downloaded_video[0].get('path'),
audio_tracks = self.downloaded_audio,
- out_path = path_join_video_audio
+ out_path = path_join_video_audio,
+ codec = self.codec
)
- print_duration_table(path_join_video_audio)
return path_join_video_audio
def __join_video_subtitles__(self, input_path: str) -> str:
@@ -449,7 +455,6 @@ class Downloader():
path_join_video_subtitle
)
- print_duration_table(path_join_video_subtitle)
return path_join_video_subtitle
def __clean__(self, out_path: str) -> None:
@@ -473,7 +478,11 @@ class Downloader():
os.rename(out_path, self.output_filename)
# Print size of the file
- console.print(Panel(f"[bold green]Download completed![/bold green]\nFile size: [bold red]{format_size(os.path.getsize(self.output_filename))}[/bold red]", title=f"{os.path.basename(self.output_filename.replace('.mp4', ''))}", border_style="green"))
+ console.print(Panel(
+ f"[bold green]Download completed![/bold green]\n"
+ f"File size: [bold red]{format_size(os.path.getsize(self.output_filename))}[/bold red]\n"
+ f"Duration: [bold]{print_duration_table(self.output_filename, show=False)}[/bold]",
+ title=f"{os.path.basename(self.output_filename.replace('.mp4', ''))}", border_style="green"))
# Delete all files except the output file
delete_files_except_one(self.base_path, os.path.basename(self.output_filename))
@@ -535,7 +544,7 @@ class Downloader():
there_is_video: bool = (len(self.downloaded_video) > 0)
there_is_audio: bool = (len(self.downloaded_audio) > 0)
there_is_subtitle: bool = (len(self.downloaded_subtitle) > 0)
- console.log(f"[cyan]Conversion [white]=> ([green]Audio: [yellow]{there_is_audio}[white], [green]Subtitle: [yellow]{there_is_subtitle}[white])")
+ console.print(f"[cyan]Conversion [white]=> ([green]Audio: [yellow]{there_is_audio}[white], [green]Subtitle: [yellow]{there_is_subtitle}[white])")
# Join audio and video
diff --git a/Src/Lib/Hls/segments.py b/Src/Lib/Hls/segments.py
index beeb831..c52d82d 100644
--- a/Src/Lib/Hls/segments.py
+++ b/Src/Lib/Hls/segments.py
@@ -31,7 +31,6 @@ from ..M3U8 import (
M3U8_UrlFix
)
-
# Config
TQDM_MAX_WORKER = config_manager.get_int('M3U8_DOWNLOAD', 'tdqm_workers')
TQDM_USE_LARGE_BAR = config_manager.get_int('M3U8_DOWNLOAD', 'tqdm_use_large_bar')
@@ -122,7 +121,7 @@ class M3U8_Segments:
m3u8_parser = M3U8_Parser()
m3u8_parser.parse_data(uri=self.url, raw_content=m3u8_content) # Parse the content of the M3U8 playlist
- console.log(f"[cyan]There is key: [yellow]{m3u8_parser.keys is not None}")
+ console.print(f"[red]There is key: [yellow]{m3u8_parser.keys is not None}")
# Check if there is an encryption key in the playlis
if m3u8_parser.keys is not None:
@@ -166,6 +165,7 @@ class M3U8_Segments:
# Update segments for estimator
self.class_ts_estimator.total_segments = len(self.segments)
+ logging.info(f"fSegmnets to donwload: [{len(self.segments)}]")
def get_info(self) -> None:
"""
@@ -220,12 +220,13 @@ class M3U8_Segments:
# Generate new user agent
headers_segments['user-agent'] = get_headers()
+ logging.info(f"Make request to get segmenet: [{index} - {len(self.segments)}]")
try:
# Make request and calculate time duration
start_time = time.time()
- response = requests.get(ts_url, headers=headers_segments, verify_ssl=REQUEST_VERIFY_SSL)
+ response = requests.get(ts_url, headers=headers_segments, verify=REQUEST_VERIFY_SSL, timeout=30)
duration = time.time() - start_time
if response.ok:
@@ -267,7 +268,7 @@ class M3U8_Segments:
while not stop_event.is_set() or not self.segment_queue.empty():
with self.condition:
while self.segment_queue.empty() and not stop_event.is_set():
- self.condition.wait(timeout=1) # Wait until a new segment is available or stop_event is set
+ self.condition.wait() # Wait until a new segment is available or stop_event is set
if stop_event.is_set():
break
@@ -311,16 +312,6 @@ class M3U8_Segments:
mininterval=0.01
)
- def signal_handler(sig, frame):
- self.ctrl_c_detected = True # Set global variable to indicate Ctrl+C detection
-
- stop_event.set()
- with self.condition:
- self.condition.notify_all() # Wake up the writer thread if it's waiting
-
- # Register the signal handler for Ctrl+C
- signal.signal(signal.SIGINT, signal_handler)
-
with ThreadPoolExecutor(max_workers=TQDM_MAX_WORKER) as executor:
# Start a separate thread to write segments to the file
@@ -330,24 +321,13 @@ class M3U8_Segments:
# Delay the start of each worker
for index, segment_url in enumerate(self.segments):
- # Check for Ctrl+C before starting each download task
- time.sleep(0.03)
-
- if self.ctrl_c_detected:
- console.log("[red]Ctrl+C detected. Stopping further downloads.")
-
- stop_event.set()
- with self.condition:
- self.condition.notify_all() # Wake up the writer thread if it's waiting
-
- break
-
# Submit the download task to the executor
executor.submit(self.make_requests_stream, segment_url, index, stop_event, progress_bar)
# Wait for all segments to be downloaded
- executor.shutdown(wait=True)
+ executor.shutdown()
stop_event.set() # Set the stop event to halt the writer thread
with self.condition:
self.condition.notify_all() # Wake up the writer thread if it's waiting
writer_thread.join() # Wait for the writer thread to finish
+
diff --git a/Src/Lib/M3U8/parser.py b/Src/Lib/M3U8/parser.py
index 2e3b647..9514dae 100644
--- a/Src/Lib/M3U8/parser.py
+++ b/Src/Lib/M3U8/parser.py
@@ -48,10 +48,6 @@ RESOLUTIONS = [
class M3U8_Codec:
- """
- Represents codec information for an M3U8 playlist.
- """
-
def __init__(self, bandwidth, codecs):
"""
Initializes the M3U8Codec object with the provided parameters.
@@ -64,20 +60,23 @@ class M3U8_Codec:
self.codecs = codecs
self.audio_codec = None
self.video_codec = None
+ self.video_codec_name = None
+ self.audio_codec_name = None
self.extract_codecs()
self.parse_codecs()
+ self.calculate_bitrates()
def extract_codecs(self):
"""
Parses the codecs information to extract audio and video codecs.
Extracted codecs are set as attributes: audio_codec and video_codec.
"""
-
- # Split the codecs string by comma
try:
+ # Split the codecs string by comma
codecs_list = self.codecs.split(',')
except Exception as e:
- logging.error(f"Cant split codec list: {self.codecs} with error {e}")
+ logging.error(f"Can't split codec list: {self.codecs} with error {e}")
+ return
# Separate audio and video codecs
for codec in codecs_list:
@@ -87,7 +86,6 @@ class M3U8_Codec:
self.audio_codec = codec
def convert_video_codec(self, video_codec_identifier) -> str:
-
"""
Convert video codec identifier to codec name.
@@ -97,6 +95,9 @@ class M3U8_Codec:
Returns:
str: Codec name corresponding to the identifier.
"""
+ if not video_codec_identifier:
+ logging.warning("No video codec identifier provided. Using default codec libx264.")
+ return "libx264" # Default
# Extract codec type from the identifier
codec_type = video_codec_identifier.split('.')[0]
@@ -107,13 +108,11 @@ class M3U8_Codec:
if codec_name:
return codec_name
-
else:
logging.warning(f"No corresponding video codec found for {video_codec_identifier}. Using default codec libx264.")
- return "libx264" # Default
-
- def convert_audio_codec(self, audio_codec_identifier) -> str:
+ return "libx264" # Default
+ def convert_audio_codec(self, audio_codec_identifier) -> str:
"""
Convert audio codec identifier to codec name.
@@ -123,6 +122,9 @@ class M3U8_Codec:
Returns:
str: Codec name corresponding to the identifier.
"""
+ if not audio_codec_identifier:
+ logging.warning("No audio codec identifier provided. Using default codec aac.")
+ return "aac" # Default
# Extract codec type from the identifier
codec_type = audio_codec_identifier.split('.')[0]
@@ -133,25 +135,33 @@ class M3U8_Codec:
if codec_name:
return codec_name
-
else:
logging.warning(f"No corresponding audio codec found for {audio_codec_identifier}. Using default codec aac.")
- return "aac" # Default
-
+ return "aac" # Default
+
def parse_codecs(self):
"""
Parse video and audio codecs.
This method updates `video_codec_name` and `audio_codec_name` attributes.
"""
-
self.video_codec_name = self.convert_video_codec(self.video_codec)
self.audio_codec_name = self.convert_audio_codec(self.audio_codec)
- def __str__(self):
+ def calculate_bitrates(self):
"""
- Returns a string representation of the M3U8Codec object.
+ Calculate video and audio bitrates based on the available bandwidth.
"""
- return f"BANDWIDTH={self.bandwidth},RESOLUTION={self.resolution},CODECS=\"{self.codecs}\""
+ if self.bandwidth:
+
+ # Define the video and audio bitrates
+ video_bitrate = int(self.bandwidth * 0.8) # Using 80% of bandwidth for video
+ audio_bitrate = self.bandwidth - video_bitrate
+
+ self.video_bitrate = video_bitrate
+ self.audio_bitrate = audio_bitrate
+ else:
+ logging.warning("No bandwidth provided. Bitrates cannot be calculated.")
+
class M3U8_Video:
diff --git a/Src/Lib/Request/my_requests.py b/Src/Lib/Request/my_requests.py
index 5c8c06c..45e774c 100644
--- a/Src/Lib/Request/my_requests.py
+++ b/Src/Lib/Request/my_requests.py
@@ -189,7 +189,7 @@ class ManageRequests:
timeout: float = HTTP_TIMEOUT,
retries: int = HTTP_RETRIES,
params: Optional[Dict[str, str]] = None,
- verify_ssl: bool = True,
+ verify: bool = True,
auth: Optional[tuple] = None,
proxy: Optional[str] = None,
cookies: Optional[Dict[str, str]] = None,
@@ -206,7 +206,7 @@ class ManageRequests:
- timeout (float, optional): The request timeout. Defaults to HTTP_TIMEOUT.
- retries (int, optional): The number of retries in case of request failure. Defaults to HTTP_RETRIES.
- params (Optional[Dict[str, str]], optional): The query parameters for the request. Defaults to None.
- - verify_ssl (bool, optional): Indicates whether SSL certificate verification should be performed. Defaults to True.
+ - verify (bool, optional): Indicates whether SSL certificate verification should be performed. Defaults to True.
- auth (Optional[tuple], optional): Tuple containing the username and password for basic authentication. Defaults to None.
- proxy (Optional[str], optional): The proxy URL. Defaults to None.
- cookies (Optional[Dict[str, str]], optional): The cookies to be included in the request. Defaults to None.
@@ -218,7 +218,7 @@ class ManageRequests:
self.timeout = timeout
self.retries = retries
self.params = params
- self.verify_ssl = verify_ssl
+ self.verify_ssl = verify
self.auth = auth
self.proxy = proxy
self.cookies = cookies
diff --git a/Src/Util/os.py b/Src/Util/os.py
index f2ab1de..a9617f5 100644
--- a/Src/Util/os.py
+++ b/Src/Util/os.py
@@ -16,6 +16,7 @@ import platform
import importlib
import subprocess
import contextlib
+import urllib.request
import importlib.metadata
from typing import List
@@ -403,6 +404,19 @@ def convert_to_hex(bytes_data: bytes) -> str:
# --> OS GET SUMMARY
+def check_internet():
+ while True:
+ try:
+ # Attempt to open a connection to a website to check for internet connection
+ urllib.request.urlopen("http://www.google.com", timeout=1)
+ console.log("[bold green]Internet is available![/bold green]")
+ break
+
+ except urllib.error.URLError:
+ console.log("[bold red]Internet is not available. Waiting...[/bold red]")
+ time.sleep(5)
+ print()
+
def get_executable_version(command):
try:
version_output = subprocess.check_output(command, stderr=subprocess.STDOUT).decode().split('\n')[0]
@@ -419,7 +433,8 @@ def get_library_version(lib_name):
return f"{lib_name}-not installed"
def get_system_summary():
-
+
+ check_internet()
console.print("[bold blue]System Summary[/bold blue][white]:")
# Python version and platform
diff --git a/config.json b/config.json
index 2603713..d769c1b 100644
--- a/config.json
+++ b/config.json
@@ -32,7 +32,10 @@
},
"M3U8_CONVERSION": {
"use_codec": false,
- "use_gpu": false,
+ "use_vcodec": true,
+ "use_acodec": true,
+ "use_bitrate": true,
+ "use_gpu": true,
"default_preset": "ultrafast",
"check_output_after_ffmpeg": false
},
diff --git a/run.py b/run.py
index 762982a..e99a551 100644
--- a/run.py
+++ b/run.py
@@ -27,34 +27,6 @@ from Src.Api.Altadefinizione import main_film as altadefinizione_film
CLOSE_CONSOLE = config_manager.get_bool('DEFAULT', 'not_close')
-def initialize():
- """
- Initialize the application.
- Checks Python version, removes temporary folder, and displays start message.
- """
-
- # Set terminal size for win 7
- if platform.system() == "Windows" and "7" in platform.version():
- os.system('mode 120, 40')
-
-
- # Check python version
- if sys.version_info < (3, 7):
- console.log("[red]Install python version > 3.7.16")
- sys.exit(0)
-
-
- # Removing temporary folder
- start_message()
-
-
- # Attempting GitHub update
- """try:
- git_update()
- except Exception as e:
- console.print(f"[blue]Req github [white]=> [red]Failed: {e}")"""
-
-
def run_function(func: Callable[..., None], close_console: bool = False) -> None:
"""
Run a given function indefinitely or once, depending on the value of close_console.
@@ -63,9 +35,6 @@ def run_function(func: Callable[..., None], close_console: bool = False) -> None
func (Callable[..., None]): The function to run.
close_console (bool, optional): Whether to close the console after running the function once. Defaults to False.
"""
-
- initialize()
-
if close_console:
while 1:
func()
@@ -73,11 +42,40 @@ def run_function(func: Callable[..., None], close_console: bool = False) -> None
func()
-def main():
-
+def initialize():
+ """
+ Initialize the application.
+ Checks Python version, removes temporary folder, and displays start message.
+ """
+
+ start_message()
+
+ # Create logger
log_not = Logger()
+
+ # Get system info
get_system_summary()
+ # Set terminal size for win 7
+ if platform.system() == "Windows" and "7" in platform.version():
+ os.system('mode 120, 40')
+
+ # Check python version
+ if sys.version_info < (3, 7):
+ console.log("[red]Install python version > 3.7.16")
+ sys.exit(0)
+
+ # Attempting GitHub update
+ try:
+ git_update()
+ except Exception as e:
+ console.print(f"[blue]Req github [white]=> [red]Failed: {e}")
+
+
+def main():
+
+ initialize()
+
# Parse command line arguments
parser = argparse.ArgumentParser(description='Script to download film and series from the internet.')
parser.add_argument('-sa', '--streaming_anime', action='store_true', help='Check into anime category')
From 8538a17b9767f27dce2598e919937fe4a1d28848 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Sat, 1 Jun 2024 17:43:50 +0200
Subject: [PATCH 04/13] Add function get server ip.
---
Src/Lib/Hls/segments.py | 2 +-
Test/t_get_server_ip_sc.py | 85 ++++++++++++++++++++++++++++++++++++++
2 files changed, 86 insertions(+), 1 deletion(-)
create mode 100644 Test/t_get_server_ip_sc.py
diff --git a/Src/Lib/Hls/segments.py b/Src/Lib/Hls/segments.py
index c52d82d..e7f2179 100644
--- a/Src/Lib/Hls/segments.py
+++ b/Src/Lib/Hls/segments.py
@@ -220,7 +220,6 @@ class M3U8_Segments:
# Generate new user agent
headers_segments['user-agent'] = get_headers()
- logging.info(f"Make request to get segmenet: [{index} - {len(self.segments)}]")
try:
@@ -228,6 +227,7 @@ class M3U8_Segments:
start_time = time.time()
response = requests.get(ts_url, headers=headers_segments, verify=REQUEST_VERIFY_SSL, timeout=30)
duration = time.time() - start_time
+ logging.info(f"Make request to get segmenet: [{index} - {len(self.segments)}] in: {duration}, len data: {len(response.content)}")
if response.ok:
diff --git a/Test/t_get_server_ip_sc.py b/Test/t_get_server_ip_sc.py
new file mode 100644
index 0000000..02bebe8
--- /dev/null
+++ b/Test/t_get_server_ip_sc.py
@@ -0,0 +1,85 @@
+# 13.05.24
+
+import socket
+import logging
+import urllib3
+from urllib.parse import urlparse, urlunparse
+
+
+import warnings
+warnings.filterwarnings("ignore", category=urllib3.exceptions.InsecureRequestWarning)
+
+
+# Variable
+url_test = "https://sc-b1-18.scws-content.net/hls/170/3/25/32503b5b-4646-4376-ad47-7766c65be7e2/audio/ita/0004-0100.ts"
+
+
+def get_ip_from_url(url):
+ """
+ Extracts the IP address from a given URL.
+
+ Args:
+ url (str): The URL from which to extract the IP address.
+
+ Returns:
+ str or None: The extracted IP address if successful, otherwise None.
+ """
+ try:
+ parsed_url = urlparse(url)
+ if not parsed_url.hostname:
+ logging.error(f"Invalid URL: {url}")
+ return None
+
+ ip_address = socket.gethostbyname(parsed_url.hostname)
+ return ip_address
+
+ except Exception as e:
+ logging.error(f"Error: {e}")
+ return None
+
+def replace_random_number(url, random_number):
+ """
+ Replaces a random number in the URL.
+
+ Args:
+ url (str): The URL in which to replace the random number.
+ random_number (int): The random number to replace in the URL.
+
+ Returns:
+ str: The modified URL with the random number replaced.
+ """
+ parsed_url = urlparse(url)
+ parts = parsed_url.netloc.split('.')
+ prefix = None
+
+ for i, part in enumerate(parts):
+ if '-' in part and part.startswith("sc-"):
+ prefix = part.split('-')[0] + '-' + part.split('-')[1] + '-'
+ new_part = prefix + f"{random_number:02d}"
+ parts[i] = new_part
+ break
+
+ new_netloc = '.'.join(parts)
+ return urlunparse((parsed_url.scheme, new_netloc, parsed_url.path, parsed_url.params, parsed_url.query, parsed_url.fragment))
+
+def main():
+ """
+ Main function to test the URL manipulation.
+ """
+ valid_ip = []
+
+ for i in range(1, 36):
+ try:
+ ip = get_ip_from_url(replace_random_number(url_test, i))
+
+ if ip:
+ valid_ip.append(ip)
+
+ except Exception as e:
+ logging.error(f"Error: {e}")
+ pass
+
+ print(f"Valid IP addresses: {sorted(valid_ip, reverse=True)}")
+
+if __name__ == '__main__':
+ main()
From 32b876a08cb9f4642932cdd2a68272c53b1c20a4 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Sun, 2 Jun 2024 08:21:34 +0200
Subject: [PATCH 05/13] Add force 1080p.
---
Src/Api/Animeunity/Core/Vix_player/player.py | 45 ++++++++++++++++++-
.../Core/Vix_player/player.py | 45 ++++++++++++++++++-
2 files changed, 88 insertions(+), 2 deletions(-)
diff --git a/Src/Api/Animeunity/Core/Vix_player/player.py b/Src/Api/Animeunity/Core/Vix_player/player.py
index bcac59a..30b30d0 100644
--- a/Src/Api/Animeunity/Core/Vix_player/player.py
+++ b/Src/Api/Animeunity/Core/Vix_player/player.py
@@ -206,4 +206,47 @@ class VideoSource:
new_url = m._replace(query=new_query) # Replace the old query string with the new one
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
- return final_url
+ if "canPlayFHD" in current_params and self.window_video.quality == "1080":
+ return final_url
+ else:
+ console.log("[red]Rebuild master playlist.")
+ return self.re_build_master()
+
+ def re_build_master(self) -> str:
+ """
+ Rebuild the master playlist.
+
+ Returns:
+ str: The rebuilt master playlist text, or an empty string if there's an error.
+ """
+ try:
+ index_resolution = None
+ master_url = f'https://vixcloud.co/playlist/{self.window_video.id}'
+ index_url = f'https://vixcloud.co/playlist/{self.window_video.id}?type=video&rendition={self.window_video.quality}p'
+
+ try:
+ # Fetch the master playlist text
+ master_text = requests.get(master_url).text
+ except requests.RequestException as e:
+ logging.error(f"Error fetching master playlist from URL: {master_url}, error: {e}")
+ return ""
+
+ # Find the resolution in the index URL
+ for resolution in [(7680, 4320), (3840, 2160), (2560, 1440), (1920, 1080), (1280, 720), (640, 480)]:
+ if str(resolution[1]) in index_url:
+ index_resolution = resolution
+ break
+
+ # Add resolution and index URL to the master playlist text
+ if index_resolution:
+ master_text += f'\n#EXT-X-STREAM-INF:BANDWIDTH=2150000,CODECS="avc1.640028,mp4a.40.2",RESOLUTION={index_resolution[0]}x{index_resolution[1]},SUBTITLES="subs"\n'
+ master_text += index_url
+
+ else:
+ logging.warning(f"No matching resolution found in index URL: {index_url}")
+
+ return master_text
+
+ except Exception as e:
+ logging.error(f"Unexpected error in re_build_master: {e}")
+ sys.exit(0)
diff --git a/Src/Api/Streamingcommunity/Core/Vix_player/player.py b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
index e72e7e0..545944c 100644
--- a/Src/Api/Streamingcommunity/Core/Vix_player/player.py
+++ b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
@@ -239,4 +239,47 @@ class VideoSource:
new_url = m._replace(query=new_query) # Replace the old query string with the new one
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
- return final_url
+ if "canPlayFHD" in current_params and self.window_video.quality == "1080":
+ return final_url
+ else:
+ console.log("[red]Rebuild master playlist.")
+ return self.re_build_master()
+
+ def re_build_master(self) -> str:
+ """
+ Rebuild the master playlist.
+
+ Returns:
+ str: The rebuilt master playlist text, or an empty string if there's an error.
+ """
+ try:
+ index_resolution = None
+ master_url = f'https://vixcloud.co/playlist/{self.window_video.id}'
+ index_url = f'https://vixcloud.co/playlist/{self.window_video.id}?type=video&rendition={self.window_video.quality}p'
+
+ try:
+ # Fetch the master playlist text
+ master_text = requests.get(master_url).text
+ except requests.RequestException as e:
+ logging.error(f"Error fetching master playlist from URL: {master_url}, error: {e}")
+ return ""
+
+ # Find the resolution in the index URL
+ for resolution in [(7680, 4320), (3840, 2160), (2560, 1440), (1920, 1080), (1280, 720), (640, 480)]:
+ if str(resolution[1]) in index_url:
+ index_resolution = resolution
+ break
+
+ # Add resolution and index URL to the master playlist text
+ if index_resolution:
+ master_text += f'\n#EXT-X-STREAM-INF:BANDWIDTH=2150000,CODECS="avc1.640028,mp4a.40.2",RESOLUTION={index_resolution[0]}x{index_resolution[1]},SUBTITLES="subs"\n'
+ master_text += index_url
+
+ else:
+ logging.warning(f"No matching resolution found in index URL: {index_url}")
+
+ return master_text
+
+ except Exception as e:
+ logging.error(f"Unexpected error in re_build_master: {e}")
+ sys.exit(0)
From 640fb87e91eb0491b2012feb3e5c9aa233646ddd Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Sun, 2 Jun 2024 09:35:36 +0200
Subject: [PATCH 06/13] Fix double logger.
---
Src/Lib/Hls/segments.py | 2 +-
Src/Util/logger.py | 4 ----
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/Src/Lib/Hls/segments.py b/Src/Lib/Hls/segments.py
index e7f2179..dc73d70 100644
--- a/Src/Lib/Hls/segments.py
+++ b/Src/Lib/Hls/segments.py
@@ -165,7 +165,7 @@ class M3U8_Segments:
# Update segments for estimator
self.class_ts_estimator.total_segments = len(self.segments)
- logging.info(f"fSegmnets to donwload: [{len(self.segments)}]")
+ logging.info(f"Segmnets to donwload: [{len(self.segments)}]")
def get_info(self) -> None:
"""
diff --git a/Src/Util/logger.py b/Src/Util/logger.py
index 216c314..0aac96b 100644
--- a/Src/Util/logger.py
+++ b/Src/Util/logger.py
@@ -53,7 +53,3 @@ class Logger:
formatter = logging.Formatter('[%(filename)s:%(lineno)s - %(funcName)20s() ] %(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
logging.getLogger('').addHandler(file_handler)
-
-
-# Output
-logger = Logger()
\ No newline at end of file
From 4677deea148b8a369e0ac5b2cd1a3d48651d2b31 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Sun, 2 Jun 2024 10:36:56 +0200
Subject: [PATCH 07/13] Finalmente fix per file con duratta errata.
---
Src/Api/Streamingcommunity/costant.py | 8 +-
Src/Lib/Hls/segments.py | 26 +-
Src/Lib/M3U8/decryption.py | 13 +-
Src/Lib/M3U8/parser.py | 23 +
Src/Lib/Request/my_requests.py | 4 +-
Src/Upload/update.py | 1 -
Src/Util/os.py | 2 +-
Test/data/TLD/creation.py | 4 +-
Test/data/m3u8/index_audio.m3u8 | 663 +++++++++++++++++++++++++-
Test/data/m3u8/index_video.m3u8 | 663 +++++++++++++++++++++++++-
Test/data/m3u8/playlist.m3u8 | 17 +-
Test/data/playlist_info.json | 10 -
Test/t_m3u8_parser.py | 22 +-
config.json | 1 -
requirements.txt | 1 +
15 files changed, 1383 insertions(+), 75 deletions(-)
delete mode 100644 Test/data/playlist_info.json
diff --git a/Src/Api/Streamingcommunity/costant.py b/Src/Api/Streamingcommunity/costant.py
index 8ac2f97..2ebb247 100644
--- a/Src/Api/Streamingcommunity/costant.py
+++ b/Src/Api/Streamingcommunity/costant.py
@@ -4,7 +4,7 @@ STREAMING_FOLDER = "streamingcommunity"
MOVIE_FOLDER = "Movie"
SERIES_FOLDER = "Serie"
-SERVER_IP = ['162.19.255.224', '162.19.255.223', '162.19.254.244', '162.19.254.232', '162.19.254.230',
- '162.19.253.242', '162.19.249.48', '162.19.245.142', '162.19.231.20', '162.19.229.177',
- '162.19.228.128', '162.19.228.127', '162.19.228.105', '141.95.1.32', '141.95.1.196',
- '141.95.1.102', '141.95.0.50', '141.95.0.248', '135.125.237.84', '135.125.233.236']
\ No newline at end of file
+SERVER_IP = ['57.129.7.85', '57.129.7.188', '57.129.7.174', '57.129.4.77', '57.129.16.196', '57.129.16.156', '57.129.16.139', '57.129.16.135', '57.129.13.175',
+ '57.129.13.157', '51.38.112.237', '51.195.107.7', '51.195.107.230', '162.19.255.78', '162.19.255.36', '162.19.255.224', '162.19.255.223', '162.19.254.244',
+ '162.19.254.232', '162.19.254.230', '162.19.253.242', '162.19.249.48', '162.19.245.142', '162.19.231.20', '162.19.229.177', '162.19.228.128', '162.19.228.127',
+ '162.19.228.105', '141.95.1.32', '141.95.1.196', '141.95.1.102', '141.95.0.50', '141.95.0.248', '135.125.237.84', '135.125.233.236']
\ No newline at end of file
diff --git a/Src/Lib/Hls/segments.py b/Src/Lib/Hls/segments.py
index dc73d70..b03db71 100644
--- a/Src/Lib/Hls/segments.py
+++ b/Src/Lib/Hls/segments.py
@@ -35,7 +35,6 @@ from ..M3U8 import (
TQDM_MAX_WORKER = config_manager.get_int('M3U8_DOWNLOAD', 'tdqm_workers')
TQDM_USE_LARGE_BAR = config_manager.get_int('M3U8_DOWNLOAD', 'tqdm_use_large_bar')
REQUEST_VERIFY_SSL = config_manager.get_bool('REQUESTS', 'verify_ssl')
-REQUEST_DISABLE_ERROR = config_manager.get_bool('REQUESTS', 'disable_error')
# Variable
@@ -96,8 +95,6 @@ class M3U8_Segments:
logging.info(f"Uri key: {key_uri}")
try:
-
- # Send HTTP GET request to fetch the key
response = requests.get(key_uri, headers=headers_index)
response.raise_for_status()
@@ -119,9 +116,10 @@ class M3U8_Segments:
- m3u8_content (str): The content of the M3U8 file.
"""
m3u8_parser = M3U8_Parser()
- m3u8_parser.parse_data(uri=self.url, raw_content=m3u8_content) # Parse the content of the M3U8 playlist
+ m3u8_parser.parse_data(uri=self.url, raw_content=m3u8_content)
- console.print(f"[red]There is key: [yellow]{m3u8_parser.keys is not None}")
+ console.log(f"[red]Expected duration after download: {m3u8_parser.get_duration()}")
+ console.log(f"[red]There is key: [yellow]{m3u8_parser.keys is not None}")
# Check if there is an encryption key in the playlis
if m3u8_parser.keys is not None:
@@ -246,12 +244,10 @@ class M3U8_Segments:
self.condition.notify() # Notify the writer thread that a new segment is available
else:
- if not REQUEST_DISABLE_ERROR:
- logging.error(f"Failed to download segment: {ts_url}")
+ logging.error(f"Failed to download segment: {ts_url}")
except Exception as e:
- if not REQUEST_DISABLE_ERROR:
- logging.error(f"Exception while downloading segment: {e}")
+ logging.error(f"Exception while downloading segment: {e}")
# Update bar
progress_bar.update(1)
@@ -265,16 +261,15 @@ class M3U8_Segments:
"""
with open(self.tmp_file_path, 'ab') as f:
- while not stop_event.is_set() or not self.segment_queue.empty():
+ while not (stop_event.is_set() and self.segment_queue.empty()): # Wait until both stop_event is set and queue is empty
with self.condition:
while self.segment_queue.empty() and not stop_event.is_set():
- self.condition.wait() # Wait until a new segment is available or stop_event is set
+ self.condition.wait() # Wait until a new segment is available or stop_event is set
- if stop_event.is_set():
+ if stop_event.is_set() and self.segment_queue.empty(): # Exit loop if both conditions are met
break
if not self.segment_queue.empty():
-
# Get the segment from the queue
index, segment_content = self.segment_queue.get()
@@ -283,10 +278,9 @@ class M3U8_Segments:
f.write(segment_content)
self.current_index += 1
self.segment_queue.task_done()
-
else:
self.segment_queue.put((index, segment_content)) # Requeue the segment if it is not the next to be written
- self.condition.notify() # Notify that a segment has been requeued
+ self.condition.notify()
def download_streams(self, add_desc):
"""
@@ -298,7 +292,7 @@ class M3U8_Segments:
stop_event = threading.Event() # Event to signal stopping
if TQDM_USE_LARGE_BAR:
- bar_format=f"{Colors.YELLOW}Downloading {Colors.WHITE}({add_desc}{Colors.WHITE}): {Colors.RED}{{percentage:.2f}}% {Colors.MAGENTA}{{bar}} {Colors.YELLOW}{{elapsed}} {Colors.WHITE}< {Colors.CYAN}{{remaining}}{{postfix}} {Colors.WHITE}]"
+ bar_format=f"{Colors.YELLOW}Downloading {Colors.WHITE}({add_desc}{Colors.WHITE}): {Colors.RED}{{percentage:.2f}}% {Colors.MAGENTA}{{bar}} {Colors.WHITE}| {Colors.YELLOW}{{n_fmt}}{Colors.WHITE} / {Colors.RED}{{total_fmt}} {Colors.WHITE}| {Colors.YELLOW}{{elapsed}} {Colors.WHITE}< {Colors.CYAN}{{remaining}}{{postfix}} {Colors.WHITE}]"
else:
bar_format=f"{Colors.YELLOW}Proc{Colors.WHITE}: {Colors.RED}{{percentage:.2f}}% {Colors.WHITE}| {Colors.CYAN}{{remaining}}{{postfix}} {Colors.WHITE}]"
diff --git a/Src/Lib/M3U8/decryption.py b/Src/Lib/M3U8/decryption.py
index b02946c..48aef02 100644
--- a/Src/Lib/M3U8/decryption.py
+++ b/Src/Lib/M3U8/decryption.py
@@ -111,17 +111,16 @@ else:
"""
if self.method == "AES":
openssl_cmd = f'openssl enc -d -aes-256-ecb -K {self.key.hex()} -nosalt'
- decrypted_data = subprocess.check_output(openssl_cmd.split(), input=ciphertext)
-
elif self.method == "AES-128":
openssl_cmd = f'openssl enc -d -aes-128-cbc -K {self.key[:16].hex()} -iv {self.iv.hex()}'
- decrypted_data = subprocess.check_output(openssl_cmd.split(), input=ciphertext)
-
elif self.method == "AES-128-CTR":
openssl_cmd = f'openssl enc -d -aes-128-ctr -K {self.key[:16].hex()} -iv {self.iv.hex()}'
- decrypted_data = subprocess.check_output(openssl_cmd.split(), input=ciphertext)
-
else:
raise ValueError("Invalid or unsupported method")
- return decrypted_data
+ try:
+ decrypted_data = subprocess.check_output(openssl_cmd.split(), input=ciphertext, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ raise ValueError(f"Decryption failed: {e.output.decode()}")
+
+ return decrypted_data
\ No newline at end of file
diff --git a/Src/Lib/M3U8/parser.py b/Src/Lib/M3U8/parser.py
index 9514dae..a29a82f 100644
--- a/Src/Lib/M3U8/parser.py
+++ b/Src/Lib/M3U8/parser.py
@@ -404,6 +404,7 @@ class M3U8_Parser:
self._video: M3U8_Video = None
self._audio: M3U8_Audio = None
self._subtitle: M3U8_Subtitle = None
+ self.duration: float = 0
self.__create_variable__()
@@ -557,6 +558,10 @@ class M3U8_Parser:
try:
for segment in m3u8_obj.segments:
+
+ # Collect all index duration
+ self.duration += segment.duration
+
if "vtt" not in segment.uri:
self.segments.append(segment.uri)
else:
@@ -573,3 +578,21 @@ class M3U8_Parser:
self._video = M3U8_Video(self.video_playlist)
self._audio = M3U8_Audio(self.audio_playlist)
self._subtitle = M3U8_Subtitle(self.subtitle_playlist)
+
+ def get_duration(self):
+ """
+ Convert duration from seconds to hours, minutes, and remaining seconds.
+
+ Parameters:
+ - seconds (float): Duration in seconds.
+
+ Returns:
+ - formatted_duration (str): Formatted duration string with hours, minutes, and seconds.
+ """
+ # Calculate hours, minutes, and remaining seconds
+ hours = int(self.duration / 3600)
+ minutes = int((self.duration % 3600) / 60)
+ remaining_seconds = int(self.duration % 60)
+
+ # Format the duration string with colors
+ return f"[yellow]{int(hours)}[red]h [yellow]{int(minutes)}[red]m [yellow]{int(remaining_seconds)}[red]s"
diff --git a/Src/Lib/Request/my_requests.py b/Src/Lib/Request/my_requests.py
index 45e774c..405d892 100644
--- a/Src/Lib/Request/my_requests.py
+++ b/Src/Lib/Request/my_requests.py
@@ -39,7 +39,6 @@ from Src.Util._jsonConfig import config_manager
HTTP_TIMEOUT = config_manager.get_int('REQUESTS', 'timeout')
HTTP_RETRIES = config_manager.get_int('REQUESTS', 'max_retry')
HTTP_DELAY = 1
-HTTP_DISABLE_ERROR = config_manager.get_bool('REQUESTS', 'disable_error')
@@ -379,8 +378,7 @@ class ManageRequests:
"""
Handle request error.
"""
- if not HTTP_DISABLE_ERROR:
- logging.error(f"Request failed for URL '{self.url}': {parse_http_error(str(e))}")
+ logging.error(f"Request failed for URL '{self.url}': {parse_http_error(str(e))}")
if self.attempt < self.retries:
logging.error(f"Retry request for URL '{self.url}' (attempt {self.attempt}/{self.retries})")
diff --git a/Src/Upload/update.py b/Src/Upload/update.py
index 82d7402..7c6e4fa 100644
--- a/Src/Upload/update.py
+++ b/Src/Upload/update.py
@@ -62,5 +62,4 @@ def update():
console.print(f"[red]{repo_name} has been downloaded [yellow]{total_download_count} [red]times, but only [yellow]{percentual_stars}% [red]of users have starred it.\n\
[cyan]Help the repository grow today by leaving a [yellow]star [cyan]and [yellow]sharing [cyan]it with others online!")
- time.sleep(1)
console.print("\n")
diff --git a/Src/Util/os.py b/Src/Util/os.py
index a9617f5..bc905a2 100644
--- a/Src/Util/os.py
+++ b/Src/Util/os.py
@@ -457,7 +457,7 @@ def get_system_summary():
logging.info(f"Exe versions: ffmpeg {ffmpeg_version}, ffprobe {ffprobe_version}")
# Optional libraries versions
- optional_libraries = ['bs4', 'certifi', 'tqdm', 'rich', 'unidecode']
+ optional_libraries = [line.strip() for line in open('requirements.txt', 'r', encoding='utf-8-sig')]
optional_libs_versions = [get_library_version(lib) for lib in optional_libraries]
console.print(f"[cyan]Libraries[white]: [bold red]{', '.join(optional_libs_versions)}[/bold red]\n")
diff --git a/Test/data/TLD/creation.py b/Test/data/TLD/creation.py
index 2116efa..d60341f 100644
--- a/Test/data/TLD/creation.py
+++ b/Test/data/TLD/creation.py
@@ -5,9 +5,6 @@ import json
from bs4 import BeautifulSoup
-# https://onshopify.com/domains/
-
-
# URL of the webpage containing the table
url = 'https://icannwiki.org/New_gTLD_Generic_Applications'
@@ -84,5 +81,6 @@ def main():
with open('data.json', 'w') as json_file:
json.dump(data, json_file)
+
if __name__ == '__main__':
main()
\ No newline at end of file
diff --git a/Test/data/m3u8/index_audio.m3u8 b/Test/data/m3u8/index_audio.m3u8
index 0928d49..d59ac13 100644
--- a/Test/data/m3u8/index_audio.m3u8
+++ b/Test/data/m3u8/index_audio.m3u8
@@ -4,10 +4,667 @@
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="/storage/enc.key",IV=0x43A6D967D5C17290D98322F5C8F6660B
#EXTINF:4.010667,
-https://sc-u10-01.scws-content.net/hls/40/6/58/6585b748-cef6-4048-a9ab-c01b9366c3b9/audio/ita/0000-0100.ts
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0000-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
#EXTINF:3.989333,
-https://sc-u10-01.scws-content.net/hls/40/6/58/6585b748-cef6-4048-a9ab-c01b9366c3b9/audio/ita/0001-0100.ts
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0001-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
#EXTINF:4.010667,
-https://sc-u10-01.scws-content.net/hls/40/6/58/6585b748-cef6-4048-a9ab-c01b9366c3b9/audio/ita/0002-0075.ts
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0002-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0003-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0004-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0005-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0006-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0007-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0008-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0009-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0010-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0011-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0012-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0013-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0014-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0015-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0016-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0017-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0018-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0019-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0020-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0021-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0022-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0023-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0024-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0025-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0026-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0027-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0028-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0029-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0030-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0031-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0032-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0033-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0034-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0035-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0036-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0037-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0038-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0039-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0040-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0041-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0042-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0043-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0044-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0045-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0046-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0047-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0048-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0049-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0050-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0051-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0052-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0053-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0054-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0055-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0056-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0057-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0058-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0059-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0060-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0061-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0062-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0063-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0064-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0065-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0066-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0067-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0068-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0069-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0070-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0071-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0072-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0073-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0074-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0075-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0076-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0077-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0078-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0079-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0080-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0081-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0082-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0083-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0084-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0085-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0086-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0087-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0088-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0089-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0090-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0091-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0092-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0093-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0094-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0095-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0096-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0097-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0098-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0099-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0100-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0101-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0102-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0103-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0104-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0105-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0106-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0107-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0108-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0109-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0110-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0111-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0112-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0113-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0114-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0115-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0116-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0117-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0118-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0119-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0120-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0121-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0122-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0123-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0124-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0125-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0126-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0127-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0128-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0129-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0130-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0131-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0132-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0133-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0134-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0135-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0136-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0137-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0138-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0139-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0140-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0141-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0142-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0143-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0144-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0145-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0146-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0147-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0148-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0149-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0150-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0151-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0152-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0153-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0154-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0155-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0156-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0157-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0158-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0159-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0160-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0161-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0162-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0163-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0164-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0165-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0166-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0167-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0168-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0169-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0170-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0171-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0172-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0173-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0174-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0175-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0176-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0177-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0178-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0179-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0180-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0181-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0182-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0183-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0184-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0185-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0186-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0187-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0188-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0189-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0190-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0191-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0192-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0193-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0194-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0195-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0196-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0197-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0198-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0199-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0200-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0201-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0202-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0203-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0204-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0205-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0206-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0207-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0208-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0209-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0210-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0211-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0212-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0213-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0214-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0215-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0216-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0217-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0218-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0219-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0220-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0221-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0222-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0223-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0224-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0225-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0226-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0227-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0228-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0229-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0230-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0231-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0232-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0233-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0234-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0235-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0236-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0237-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0238-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0239-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0240-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0241-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0242-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0243-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0244-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0245-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0246-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0247-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0248-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0249-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0250-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0251-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0252-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0253-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0254-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0255-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0256-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0257-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0258-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0259-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0260-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0261-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0262-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0263-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0264-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0265-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0266-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0267-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0268-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0269-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0270-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0271-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0272-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0273-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0274-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0275-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0276-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0277-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0278-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0279-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0280-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0281-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0282-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0283-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0284-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0285-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0286-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0287-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0288-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0289-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0290-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0291-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0292-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0293-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0294-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0295-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0296-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0297-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0298-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0299-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0300-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0301-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0302-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0303-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0304-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0305-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0306-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0307-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0308-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0309-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0310-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0311-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0312-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0313-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0314-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0315-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0316-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0317-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0318-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0319-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0320-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0321-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0322-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0323-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0324-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0325-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0326-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0327-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0328-0100.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:3.989333,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0329-0075.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:4.010667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0330-0025.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
+#EXTINF:0.266667,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/audio/ita/0331-0025.ts?token=r1bvf1Wwun-McFrLkW1jyQ&expires=1722499729
#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/Test/data/m3u8/index_video.m3u8 b/Test/data/m3u8/index_video.m3u8
index 49b39ec..4274422 100644
--- a/Test/data/m3u8/index_video.m3u8
+++ b/Test/data/m3u8/index_video.m3u8
@@ -4,10 +4,667 @@
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="/storage/enc.key",IV=0x43A6D967D5C17290D98322F5C8F6660B
#EXTINF:4,
-https://sc-u10-01.scws-content.net/hls/40/6/58/6585b748-cef6-4048-a9ab-c01b9366c3b9/video/720p/0000-0250.ts
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0000-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
#EXTINF:4,
-https://sc-u10-01.scws-content.net/hls/40/6/58/6585b748-cef6-4048-a9ab-c01b9366c3b9/video/720p/0001-0250.ts
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0001-0250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
#EXTINF:4,
-https://sc-u10-01.scws-content.net/hls/40/6/58/6585b748-cef6-4048-a9ab-c01b9366c3b9/video/720p/0002-0075.ts
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0002-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0003-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0004-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0005-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0006-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0007-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0008-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0009-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0010-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0011-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0012-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0013-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0014-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0015-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0016-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0017-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0018-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0019-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0020-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0021-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0022-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0023-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0024-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0025-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0026-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0027-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0028-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0029-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0030-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0031-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0032-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0033-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0034-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0035-3000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0036-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0037-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0038-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0039-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0040-2500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0041-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0042-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0043-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0044-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0045-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0046-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0047-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0048-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0049-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0050-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0051-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0052-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0053-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0054-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0055-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0056-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0057-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0058-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0059-0250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0060-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0061-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0062-2500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0063-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0064-2500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0065-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0066-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0067-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0068-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0069-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0070-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0071-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0072-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0073-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0074-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0075-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0076-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0077-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0078-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0079-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0080-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0081-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0082-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0083-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0084-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0085-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0086-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0087-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0088-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0089-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0090-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0091-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0092-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0093-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0094-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0095-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0096-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0097-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0098-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0099-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0100-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0101-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0102-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0103-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0104-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0105-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0106-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0107-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0108-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0109-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0110-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0111-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0112-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0113-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0114-2000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0115-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0116-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0117-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0118-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0119-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0120-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0121-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0122-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0123-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0124-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0125-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0126-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0127-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0128-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0129-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0130-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0131-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0132-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0133-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0134-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0135-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0136-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0137-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0138-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0139-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0140-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0141-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0142-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0143-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0144-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0145-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0146-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0147-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0148-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0149-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0150-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0151-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0152-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0153-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0154-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0155-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0156-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0157-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0158-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0159-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0160-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0161-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0162-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0163-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0164-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0165-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0166-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0167-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0168-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0169-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0170-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0171-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0172-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0173-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0174-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0175-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0176-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0177-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0178-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0179-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0180-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0181-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0182-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0183-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0184-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0185-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0186-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0187-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0188-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0189-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0190-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0191-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0192-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0193-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0194-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0195-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0196-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0197-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0198-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0199-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0200-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0201-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0202-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0203-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0204-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0205-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0206-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0207-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0208-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0209-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0210-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0211-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0212-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0213-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0214-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0215-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0216-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0217-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0218-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0219-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0220-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0221-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0222-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0223-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0224-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0225-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0226-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0227-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0228-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0229-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0230-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0231-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0232-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0233-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0234-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0235-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0236-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0237-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0238-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0239-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0240-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0241-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0242-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0243-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0244-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0245-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0246-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0247-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0248-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0249-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0250-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0251-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0252-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0253-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0254-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0255-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0256-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0257-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0258-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0259-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0260-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0261-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0262-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0263-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0264-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0265-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0266-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0267-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0268-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0269-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0270-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0271-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0272-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0273-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0274-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0275-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0276-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0277-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0278-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0279-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0280-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0281-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0282-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0283-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0284-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0285-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0286-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0287-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0288-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0289-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0290-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0291-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0292-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0293-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0294-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0295-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0296-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0297-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0298-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0299-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0300-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0301-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0302-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0303-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0304-1500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0305-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0306-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0307-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0308-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0309-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0310-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0311-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0312-1750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0313-0750.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0314-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0315-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0316-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0317-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0318-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0319-1000.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0320-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0321-1250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0322-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0323-0075.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0324-0125.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0325-0250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0326-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0327-0500.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0328-0250.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0329-0100.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:4,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0330-0100.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
+#EXTINF:0.25,
+https://sc-u2-01.scws-content.net/hls/190/4/13/4130abf2-c2e7-4b66-8907-f11b4ee38a27/video/1080p/0331-0050.ts?token=Yce8pl2-m8bk6uQvq7W0fg&expires=1722499729
#EXT-X-ENDLIST
\ No newline at end of file
diff --git a/Test/data/m3u8/playlist.m3u8 b/Test/data/m3u8/playlist.m3u8
index f047f01..5fd46ff 100644
--- a/Test/data/m3u8/playlist.m3u8
+++ b/Test/data/m3u8/playlist.m3u8
@@ -1,11 +1,12 @@
#EXTM3U
-#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="Italian",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="ita",URI="https://vixcloud.co/playlist/213349?type=audio&rendition=ita&token=J0FBqnixXmTN24xdMdxAVg&expires=1720013276"
-
-#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English [CC]",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE="eng",URI="https://vixcloud.co/playlist/213349?type=subtitle&rendition=3-eng&token=J0FBqnixXmTN24xdMdxAVg&expires=1720013276"
-#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Czech",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE="cze",URI="https://vixcloud.co/playlist/213349?type=subtitle&rendition=4-cze&token=J0FBqnixXmTN24xdMdxAVg&expires=1720013276"
-
+#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="Italian",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="ita",URI="https://vixcloud.co/playlist/175761?type=audio&rendition=ita&token=AfHdAGc26qqpBDVFAdKJCQ&expires=1722501194&edge=sc-u2-01"
+#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE="eng",URI="https://vixcloud.co/playlist/175761?type=audio&rendition=eng&token=AfHdAGc26qqpBDVFAdKJCQ&expires=1722501194&edge=sc-u2-01"
+#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE="eng",URI="https://vixcloud.co/playlist/175761?type=subtitle&rendition=eng&token=AfHdAGc26qqpBDVFAdKJCQ&expires=1722501194&edge=sc-u2-01"
+#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Italian [Forced]",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="forced-ita",URI="https://vixcloud.co/playlist/175761?type=subtitle&rendition=forced-ita&token=AfHdAGc26qqpBDVFAdKJCQ&expires=1722501194&edge=sc-u2-01"
+#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Italian",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE="ita",URI="https://vixcloud.co/playlist/175761?type=subtitle&rendition=ita&token=AfHdAGc26qqpBDVFAdKJCQ&expires=1722501194&edge=sc-u2-01"
#EXT-X-STREAM-INF:BANDWIDTH=1200000,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=854x480,AUDIO="audio",SUBTITLES="subs"
-https://vixcloud.co/playlist/213349?type=video&rendition=480p&token=WcQHF0VYTJnnWXRVzGyI4A&expires=1720013276
-
+https://vixcloud.co/playlist/175761?type=video&rendition=480p&token=VQk6xhvJbSGMsktylrOqLg&expires=1722501194&edge=sc-u2-01
#EXT-X-STREAM-INF:BANDWIDTH=2150000,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1280x720,AUDIO="audio",SUBTITLES="subs"
-https://vixcloud.co/playlist/213349?type=video&rendition=720p&token=pYMwBEGivMnsWlzTJodYQw&expires=1720013276
\ No newline at end of file
+https://vixcloud.co/playlist/175761?type=video&rendition=720p&token=ecGWDJYeeYgEJTP_fjDQKQ&expires=1722501194&edge=sc-u2-01
+#EXT-X-STREAM-INF:BANDWIDTH=4500000,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1920x1080,AUDIO="audio",SUBTITLES="subs"
+https://vixcloud.co/playlist/175761?type=video&rendition=1080p&token=AhO8JTM1VfOMfrZFpEfjUw&expires=1722501194&edge=sc-u2-01
\ No newline at end of file
diff --git a/Test/data/playlist_info.json b/Test/data/playlist_info.json
deleted file mode 100644
index 26d3f2b..0000000
--- a/Test/data/playlist_info.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "2024-5": {
- "token": "csVhbgxqG_z_tjvJiy1IiA",
- "token360p": "",
- "token480p": "S7MTy30iN4BcxC-sXt0fOw",
- "token720p": "fW_SEvaLezh5bD_iKDxcpw",
- "token1080p": "HSuRzJwwFYR55KhtOAC85Q",
- "expires": "1720963565"
- }
-}
\ No newline at end of file
diff --git a/Test/t_m3u8_parser.py b/Test/t_m3u8_parser.py
index 88bb31f..c6468e5 100644
--- a/Test/t_m3u8_parser.py
+++ b/Test/t_m3u8_parser.py
@@ -23,23 +23,15 @@ from Src.Lib.M3U8 import M3U8_Parser
# Test data
obj_m3u8_parser = M3U8_Parser()
base_path_file = os.path.join('Test', 'data', 'm3u8')
+
+
+# Collect all index
+index_video = read_file(os.path.join(base_path_file, "index_video.m3u8"))
index_audio = read_file(os.path.join(base_path_file, "index_audio.m3u8"))
index_subtitle = read_file(os.path.join(base_path_file,"index_subtitle.m3u8"))
-index_video = read_file(os.path.join(base_path_file, "index_video.m3u8"))
playlist = read_file(os.path.join(base_path_file, "playlist.m3u8"))
-print("AUDIO: ")
-print(M3U8(index_audio).data)
-print()
-
-print("SUBTITLE: ")
-print(M3U8(index_subtitle).data)
-print()
-
-print("INDEX: ")
-print(M3U8(index_video).data)
-print()
-
-print("PLAYLIST: ")
-print(M3U8(playlist).data)
+# Test class
+obj_m3u8_parser.parse_data("http", index_audio)
+print(f"Duration : {obj_m3u8_parser.get_duration()}")
diff --git a/config.json b/config.json
index d769c1b..b07741d 100644
--- a/config.json
+++ b/config.json
@@ -10,7 +10,6 @@
"not_close": false
},
"REQUESTS": {
- "disable_error": false,
"timeout": 10,
"max_retry": 3,
"verify_ssl": false,
diff --git a/requirements.txt b/requirements.txt
index 21218f8..3f1f64e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
bs4
+certifi
tqdm
rich
unidecode
\ No newline at end of file
From d2a9165f7d2fab7af030f9d3cdb677b3b974fb10 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Sun, 2 Jun 2024 16:02:47 +0200
Subject: [PATCH 08/13] Remove stop_event
---
Src/Lib/FFmpeg/util.py | 4 +--
Src/Lib/Hls/segments.py | 65 ++++++++++++++++-------------------------
2 files changed, 27 insertions(+), 42 deletions(-)
diff --git a/Src/Lib/FFmpeg/util.py b/Src/Lib/FFmpeg/util.py
index 10ef22c..1f46cf4 100644
--- a/Src/Lib/FFmpeg/util.py
+++ b/Src/Lib/FFmpeg/util.py
@@ -71,8 +71,8 @@ def get_video_duration(file_path: str) -> float:
return float(probe_result['format']['duration'])
except Exception as e:
- logging.error(f"Error: {e}")
- return None
+ logging.error(f"Error get video duration: {e}")
+ sys.exit(0)
def format_duration(seconds: float) -> Tuple[int, int, int]:
diff --git a/Src/Lib/Hls/segments.py b/Src/Lib/Hls/segments.py
index b03db71..9a5e428 100644
--- a/Src/Lib/Hls/segments.py
+++ b/Src/Lib/Hls/segments.py
@@ -5,7 +5,6 @@ import sys
import time
import queue
import threading
-import signal
import logging
import binascii
from concurrent.futures import ThreadPoolExecutor
@@ -53,18 +52,20 @@ class M3U8_Segments:
- tmp_folder (str): The temporary folder to store downloaded segments.
"""
self.url = url
+ self.fake_proxy = False
self.tmp_folder = tmp_folder
- self.decryption: M3U8_Decryption = None # Initialize decryption as None
- self.segment_queue = queue.PriorityQueue() # Priority queue to maintain the order of segments
- self.current_index = 0 # Index of the current segment to be written
- self.tmp_file_path = os.path.join(self.tmp_folder, "0.ts") # Path to the temporary file
- self.condition = threading.Condition() # Condition variable for thread synchronization
- self.ctrl_c_detected = False # Global variable to track Ctrl+C detection
+ self.tmp_file_path = os.path.join(self.tmp_folder, "0.ts")
+ os.makedirs(self.tmp_folder, exist_ok=True)
- os.makedirs(self.tmp_folder, exist_ok=True) # Create the temporary folder if it does not exist
+ # Util class
+ self.decryption: M3U8_Decryption = None
self.class_ts_estimator = M3U8_Ts_Estimator(0)
self.class_url_fixer = M3U8_UrlFix(url)
- self.fake_proxy = False
+
+ # Sync
+ self.current_index = 0 # Index of the current segment to be written
+ self.segment_queue = queue.PriorityQueue() # Priority queue to maintain the order of segments
+ self.condition = threading.Condition() # Condition variable for thread synchronization
def add_server_ip(self, list_ip):
"""
@@ -201,21 +202,16 @@ class M3U8_Segments:
return urlunparse(parsed_url)
- def make_requests_stream(self, ts_url: str, index: int, stop_event: threading.Event, progress_bar: tqdm) -> None:
+ def make_requests_stream(self, ts_url: str, index: int, progress_bar: tqdm) -> None:
"""
Downloads a TS segment and adds it to the segment queue.
Args:
- ts_url (str): The URL of the TS segment.
- index (int): The index of the segment.
- - stop_event (threading.Event): Event to signal the stop of downloading.
- progress_bar (tqdm): Progress counter for tracking download progress.
- - add_desc (str): Additional description for the progress bar.
"""
- if stop_event.is_set():
- return # Exit if the stop event is set
-
# Generate new user agent
headers_segments['user-agent'] = get_headers()
@@ -225,8 +221,8 @@ class M3U8_Segments:
start_time = time.time()
response = requests.get(ts_url, headers=headers_segments, verify=REQUEST_VERIFY_SSL, timeout=30)
duration = time.time() - start_time
- logging.info(f"Make request to get segmenet: [{index} - {len(self.segments)}] in: {duration}, len data: {len(response.content)}")
-
+ logging.info(f"Make request to get segment: [{index} - {len(self.segments)}] in: {duration}, len data: {len(response.content)}")
+
if response.ok:
# Get the content of the segment
@@ -242,7 +238,6 @@ class M3U8_Segments:
with self.condition:
self.segment_queue.put((index, segment_content)) # Add the segment to the queue
self.condition.notify() # Notify the writer thread that a new segment is available
-
else:
logging.error(f"Failed to download segment: {ts_url}")
@@ -252,22 +247,18 @@ class M3U8_Segments:
# Update bar
progress_bar.update(1)
- def write_segments_to_file(self, stop_event: threading.Event):
+ def write_segments_to_file(self):
"""
Writes downloaded segments to a file in the correct order.
-
- Args:
- - stop_event (threading.Event): Event to signal the stop of writing.
"""
-
with open(self.tmp_file_path, 'ab') as f:
- while not (stop_event.is_set() and self.segment_queue.empty()): # Wait until both stop_event is set and queue is empty
+ while True:
with self.condition:
- while self.segment_queue.empty() and not stop_event.is_set():
- self.condition.wait() # Wait until a new segment is available or stop_event is set
+ while self.segment_queue.empty() and self.current_index < len(self.segments):
+ self.condition.wait() # Wait until a new segment is available or all segments are downloaded
- if stop_event.is_set() and self.segment_queue.empty(): # Exit loop if both conditions are met
- break
+ if self.segment_queue.empty() and self.current_index >= len(self.segments):
+ break # Exit loop if all segments have been processed
if not self.segment_queue.empty():
# Get the segment from the queue
@@ -279,7 +270,7 @@ class M3U8_Segments:
self.current_index += 1
self.segment_queue.task_done()
else:
- self.segment_queue.put((index, segment_content)) # Requeue the segment if it is not the next to be written
+ self.segment_queue.put((index, segment_content)) # Requeue the segment if it is not the next to be written
self.condition.notify()
def download_streams(self, add_desc):
@@ -289,8 +280,6 @@ class M3U8_Segments:
Args:
- add_desc (str): Additional description for the progress bar.
"""
- stop_event = threading.Event() # Event to signal stopping
-
if TQDM_USE_LARGE_BAR:
bar_format=f"{Colors.YELLOW}Downloading {Colors.WHITE}({add_desc}{Colors.WHITE}): {Colors.RED}{{percentage:.2f}}% {Colors.MAGENTA}{{bar}} {Colors.WHITE}| {Colors.YELLOW}{{n_fmt}}{Colors.WHITE} / {Colors.RED}{{total_fmt}} {Colors.WHITE}| {Colors.YELLOW}{{elapsed}} {Colors.WHITE}< {Colors.CYAN}{{remaining}}{{postfix}} {Colors.WHITE}]"
else:
@@ -300,28 +289,24 @@ class M3U8_Segments:
total=len(self.segments),
unit='s',
ascii='░▒█',
- bar_format=bar_format,
- dynamic_ncols=True,
- ncols=80,
- mininterval=0.01
+ bar_format=bar_format
)
with ThreadPoolExecutor(max_workers=TQDM_MAX_WORKER) as executor:
# Start a separate thread to write segments to the file
- writer_thread = threading.Thread(target=self.write_segments_to_file, args=(stop_event,))
+ writer_thread = threading.Thread(target=self.write_segments_to_file)
writer_thread.start()
- # Delay the start of each worker
+ # Start all workers
for index, segment_url in enumerate(self.segments):
# Submit the download task to the executor
- executor.submit(self.make_requests_stream, segment_url, index, stop_event, progress_bar)
+ executor.submit(self.make_requests_stream, segment_url, index, progress_bar)
# Wait for all segments to be downloaded
executor.shutdown()
- stop_event.set() # Set the stop event to halt the writer thread
+
with self.condition:
self.condition.notify_all() # Wake up the writer thread if it's waiting
writer_thread.join() # Wait for the writer thread to finish
-
From a030a2ef3b5cfe4248e204b98b8be005a5f4d4a7 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Sun, 2 Jun 2024 16:08:08 +0200
Subject: [PATCH 09/13] Rename repo.
---
Src/Upload/version.py | 4 ++--
Src/Util/message.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Src/Upload/version.py b/Src/Upload/version.py
index bb50b0f..c69e058 100644
--- a/Src/Upload/version.py
+++ b/Src/Upload/version.py
@@ -1,5 +1,5 @@
-__title__ = 'Streaming_community'
+__title__ = 'StreamingCommunity'
__version__ = 'v1.1.0'
-__author__ = 'Ghost6446'
+__author__ = 'Lovi-0'
__description__ = 'A command-line program to download film'
__copyright__ = 'Copyright 2024'
diff --git a/Src/Util/message.py b/Src/Util/message.py
index 4a5706c..b20000d 100644
--- a/Src/Util/message.py
+++ b/Src/Util/message.py
@@ -41,7 +41,7 @@ def start_message():
if SHOW:
console.print(f"[bold yellow]{msg}")
- console.print(f"[magenta]Created by: Ghost6446\n")
+ console.print(f"[magenta]Created by: Lovi\n")
row = "-" * console.width
console.print(f"[yellow]{row} \n")
\ No newline at end of file
From 37e75370b0815299334461260643dff75317e657 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Tue, 4 Jun 2024 22:06:46 +0200
Subject: [PATCH 10/13] Only 4 workers.
---
Src/Api/Animeunity/Core/Vix_player/player.py | 45 +------------------
.../Core/Vix_player/player.py | 45 +------------------
Src/Api/Streamingcommunity/costant.py | 5 ---
Src/Api/Streamingcommunity/film.py | 4 +-
Src/Api/Streamingcommunity/series.py | 4 +-
Src/Lib/Hls/segments.py | 31 +++++++++++++
config.json | 2 +-
7 files changed, 38 insertions(+), 98 deletions(-)
diff --git a/Src/Api/Animeunity/Core/Vix_player/player.py b/Src/Api/Animeunity/Core/Vix_player/player.py
index 30b30d0..bcac59a 100644
--- a/Src/Api/Animeunity/Core/Vix_player/player.py
+++ b/Src/Api/Animeunity/Core/Vix_player/player.py
@@ -206,47 +206,4 @@ class VideoSource:
new_url = m._replace(query=new_query) # Replace the old query string with the new one
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
- if "canPlayFHD" in current_params and self.window_video.quality == "1080":
- return final_url
- else:
- console.log("[red]Rebuild master playlist.")
- return self.re_build_master()
-
- def re_build_master(self) -> str:
- """
- Rebuild the master playlist.
-
- Returns:
- str: The rebuilt master playlist text, or an empty string if there's an error.
- """
- try:
- index_resolution = None
- master_url = f'https://vixcloud.co/playlist/{self.window_video.id}'
- index_url = f'https://vixcloud.co/playlist/{self.window_video.id}?type=video&rendition={self.window_video.quality}p'
-
- try:
- # Fetch the master playlist text
- master_text = requests.get(master_url).text
- except requests.RequestException as e:
- logging.error(f"Error fetching master playlist from URL: {master_url}, error: {e}")
- return ""
-
- # Find the resolution in the index URL
- for resolution in [(7680, 4320), (3840, 2160), (2560, 1440), (1920, 1080), (1280, 720), (640, 480)]:
- if str(resolution[1]) in index_url:
- index_resolution = resolution
- break
-
- # Add resolution and index URL to the master playlist text
- if index_resolution:
- master_text += f'\n#EXT-X-STREAM-INF:BANDWIDTH=2150000,CODECS="avc1.640028,mp4a.40.2",RESOLUTION={index_resolution[0]}x{index_resolution[1]},SUBTITLES="subs"\n'
- master_text += index_url
-
- else:
- logging.warning(f"No matching resolution found in index URL: {index_url}")
-
- return master_text
-
- except Exception as e:
- logging.error(f"Unexpected error in re_build_master: {e}")
- sys.exit(0)
+ return final_url
diff --git a/Src/Api/Streamingcommunity/Core/Vix_player/player.py b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
index 545944c..e72e7e0 100644
--- a/Src/Api/Streamingcommunity/Core/Vix_player/player.py
+++ b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
@@ -239,47 +239,4 @@ class VideoSource:
new_url = m._replace(query=new_query) # Replace the old query string with the new one
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
- if "canPlayFHD" in current_params and self.window_video.quality == "1080":
- return final_url
- else:
- console.log("[red]Rebuild master playlist.")
- return self.re_build_master()
-
- def re_build_master(self) -> str:
- """
- Rebuild the master playlist.
-
- Returns:
- str: The rebuilt master playlist text, or an empty string if there's an error.
- """
- try:
- index_resolution = None
- master_url = f'https://vixcloud.co/playlist/{self.window_video.id}'
- index_url = f'https://vixcloud.co/playlist/{self.window_video.id}?type=video&rendition={self.window_video.quality}p'
-
- try:
- # Fetch the master playlist text
- master_text = requests.get(master_url).text
- except requests.RequestException as e:
- logging.error(f"Error fetching master playlist from URL: {master_url}, error: {e}")
- return ""
-
- # Find the resolution in the index URL
- for resolution in [(7680, 4320), (3840, 2160), (2560, 1440), (1920, 1080), (1280, 720), (640, 480)]:
- if str(resolution[1]) in index_url:
- index_resolution = resolution
- break
-
- # Add resolution and index URL to the master playlist text
- if index_resolution:
- master_text += f'\n#EXT-X-STREAM-INF:BANDWIDTH=2150000,CODECS="avc1.640028,mp4a.40.2",RESOLUTION={index_resolution[0]}x{index_resolution[1]},SUBTITLES="subs"\n'
- master_text += index_url
-
- else:
- logging.warning(f"No matching resolution found in index URL: {index_url}")
-
- return master_text
-
- except Exception as e:
- logging.error(f"Unexpected error in re_build_master: {e}")
- sys.exit(0)
+ return final_url
diff --git a/Src/Api/Streamingcommunity/costant.py b/Src/Api/Streamingcommunity/costant.py
index 2ebb247..6038c67 100644
--- a/Src/Api/Streamingcommunity/costant.py
+++ b/Src/Api/Streamingcommunity/costant.py
@@ -3,8 +3,3 @@
STREAMING_FOLDER = "streamingcommunity"
MOVIE_FOLDER = "Movie"
SERIES_FOLDER = "Serie"
-
-SERVER_IP = ['57.129.7.85', '57.129.7.188', '57.129.7.174', '57.129.4.77', '57.129.16.196', '57.129.16.156', '57.129.16.139', '57.129.16.135', '57.129.13.175',
- '57.129.13.157', '51.38.112.237', '51.195.107.7', '51.195.107.230', '162.19.255.78', '162.19.255.36', '162.19.255.224', '162.19.255.223', '162.19.254.244',
- '162.19.254.232', '162.19.254.230', '162.19.253.242', '162.19.249.48', '162.19.245.142', '162.19.231.20', '162.19.229.177', '162.19.228.128', '162.19.228.127',
- '162.19.228.105', '141.95.1.32', '141.95.1.196', '141.95.1.102', '141.95.0.50', '141.95.0.248', '135.125.237.84', '135.125.233.236']
\ No newline at end of file
diff --git a/Src/Api/Streamingcommunity/film.py b/Src/Api/Streamingcommunity/film.py
index 47b0e90..2b9d7bf 100644
--- a/Src/Api/Streamingcommunity/film.py
+++ b/Src/Api/Streamingcommunity/film.py
@@ -18,7 +18,7 @@ from .Core.Vix_player.player import VideoSource
# Config
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
-from .costant import STREAMING_FOLDER, MOVIE_FOLDER, SERVER_IP
+from .costant import STREAMING_FOLDER, MOVIE_FOLDER
# Variable
@@ -59,4 +59,4 @@ def download_film(id_film: str, title_name: str, domain: str):
Downloader(
m3u8_playlist = master_playlist,
output_filename = os.path.join(mp4_path, mp4_format)
- ).start(SERVER_IP)
\ No newline at end of file
+ ).start()
\ No newline at end of file
diff --git a/Src/Api/Streamingcommunity/series.py b/Src/Api/Streamingcommunity/series.py
index f10be43..9b2ecc0 100644
--- a/Src/Api/Streamingcommunity/series.py
+++ b/Src/Api/Streamingcommunity/series.py
@@ -20,7 +20,7 @@ from .Core.Util import manage_selection, map_episode_title
# Config
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
-from .costant import STREAMING_FOLDER, SERIES_FOLDER, SERVER_IP
+from .costant import STREAMING_FOLDER, SERIES_FOLDER
# Variable
@@ -96,7 +96,7 @@ def donwload_video(tv_name: str, index_season_selected: int, index_episode_selec
Downloader(
m3u8_playlist = master_playlist,
output_filename = os.path.join(mp4_path, mp4_name)
- ).start(SERVER_IP)
+ ).start()
def donwload_episode(tv_name: str, index_season_selected: int, donwload_all: bool = False) -> None:
diff --git a/Src/Lib/Hls/segments.py b/Src/Lib/Hls/segments.py
index 9a5e428..fe2a131 100644
--- a/Src/Lib/Hls/segments.py
+++ b/Src/Lib/Hls/segments.py
@@ -109,6 +109,34 @@ class M3U8_Segments:
logging.info(f"Key: ('hex': {hex_content}, 'byte': {byte_content})")
return byte_content
+ def __test_ip(self):
+ """
+ Tests each proxy IP by sending a request to a corresponding segment URL.
+ """
+
+ failed_ips = []
+
+ for i in range(len(self.fake_proxy_ip)):
+ url_to_test = self.segments[i]
+
+ try:
+
+ # Attempt to send a GET request to the URL
+ requests.get(url_to_test, verify=self.verify_ssl)
+ except:
+
+ # Log the error and add the IP to the list of failed IPs
+ logging.error(f"Failed to make request using IP in this request: {url_to_test}")
+ failed_ips.append(i)
+
+ # Remove the failed IPs from the fake_proxy_ip list
+ self.fake_proxy_ip = [ip for j, ip in enumerate(self.fake_proxy_ip) if j not in failed_ips]
+
+ # Exit the program if 50% requests failed
+ if len(failed_ips) / 2 > len(self.fake_proxy_ip):
+ logging.error("All requests with ip failed. Exiting the program.")
+ sys.exit(0)
+
def parse_data(self, m3u8_content: str) -> None:
"""
Parses the M3U8 content to extract segment information.
@@ -156,6 +184,9 @@ class M3U8_Segments:
self.segments[i] = self.__gen_proxy__(segment_url, self.segments.index(segment_url))
+ # Test new url with ip
+ self.__test_ip()
+
# Save new playlist of segment
path_m3u8_file = os.path.join(self.tmp_folder, "playlist_fix.m3u8")
with open(path_m3u8_file, "w") as file:
diff --git a/config.json b/config.json
index b07741d..4cfd9e6 100644
--- a/config.json
+++ b/config.json
@@ -17,7 +17,7 @@
"segments": { "user-agent": ""}
},
"M3U8_DOWNLOAD": {
- "tdqm_workers": 30,
+ "tdqm_workers": 4,
"tqdm_use_large_bar": true,
"download_video": true,
"download_audio": true,
From 4553cf9f45e95facdd17444bcd2786cc1bcaf2d4 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Tue, 4 Jun 2024 23:18:16 +0200
Subject: [PATCH 11/13] Auto switch proxy.
---
Src/Api/Animeunity/anime.py | 4 +-
Src/Api/Animeunity/costant.py | 4 +-
.../Core/Vix_player/player.py | 2 +-
Src/Api/Streamingcommunity/costant.py | 2 +
Src/Api/Streamingcommunity/film.py | 4 +-
Src/Api/Streamingcommunity/series.py | 4 +-
Src/Lib/Hls/segments.py | 43 +++++++++++++------
7 files changed, 41 insertions(+), 22 deletions(-)
diff --git a/Src/Api/Animeunity/anime.py b/Src/Api/Animeunity/anime.py
index 26a6357..79a2355 100644
--- a/Src/Api/Animeunity/anime.py
+++ b/Src/Api/Animeunity/anime.py
@@ -18,7 +18,7 @@ from .Core.Util import manage_selection
# Config
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
-from .costant import ANIME_FOLDER, SERIES_FOLDER, MOVIE_FOLDER
+from .costant import ANIME_FOLDER, SERIES_FOLDER, MOVIE_FOLDER, STATIC_IP_SERVER
# Variable
@@ -61,7 +61,7 @@ def download_episode(index_select: int):
)
# Start downloading
- obj_download.start()
+ obj_download.start(STATIC_IP_SERVER)
def donwload_series(tv_id: int, tv_name: str):
diff --git a/Src/Api/Animeunity/costant.py b/Src/Api/Animeunity/costant.py
index 68ec402..28f0252 100644
--- a/Src/Api/Animeunity/costant.py
+++ b/Src/Api/Animeunity/costant.py
@@ -2,4 +2,6 @@
ANIME_FOLDER = "animeunity"
SERIES_FOLDER= "Serie"
-MOVIE_FOLDER = "Movie"
\ No newline at end of file
+MOVIE_FOLDER = "Movie"
+
+STATIC_IP_SERVER = ['57.129.7.85', '57.129.7.188', '57.129.7.174', '57.129.4.77', '57.129.16.196', '57.129.16.156', '57.129.16.139', '57.129.16.135', '57.129.13.175', '57.129.13.157', '51.38.112.237', '51.195.107.7', '51.195.107.230', '162.19.255.78', '162.19.255.36', '162.19.255.224', '162.19.255.223', '162.19.254.244', '162.19.254.232', '162.19.254.230', '162.19.253.242', '162.19.249.48', '162.19.245.142', '162.19.231.20', '162.19.229.177', '162.19.228.128', '162.19.228.127', '162.19.228.105', '141.95.1.32', '141.95.1.196', '141.95.1.102', '141.95.0.50', '141.95.0.248', '135.125.237.84', '135.125.233.236']
\ No newline at end of file
diff --git a/Src/Api/Streamingcommunity/Core/Vix_player/player.py b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
index e72e7e0..bd72041 100644
--- a/Src/Api/Streamingcommunity/Core/Vix_player/player.py
+++ b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
@@ -238,5 +238,5 @@ class VideoSource:
new_query = urlencode(final_params) # Encode final_params into a query string
new_url = m._replace(query=new_query) # Replace the old query string with the new one
final_url = urlunparse(new_url) # Construct the final URL from the modified parts
-
+
return final_url
diff --git a/Src/Api/Streamingcommunity/costant.py b/Src/Api/Streamingcommunity/costant.py
index 6038c67..de48a7f 100644
--- a/Src/Api/Streamingcommunity/costant.py
+++ b/Src/Api/Streamingcommunity/costant.py
@@ -3,3 +3,5 @@
STREAMING_FOLDER = "streamingcommunity"
MOVIE_FOLDER = "Movie"
SERIES_FOLDER = "Serie"
+
+STATIC_IP_SERVER = ['57.129.7.85', '57.129.7.188', '57.129.7.174', '57.129.4.77', '57.129.16.196', '57.129.16.156', '57.129.16.139', '57.129.16.135', '57.129.13.175', '57.129.13.157', '51.38.112.237', '51.195.107.7', '51.195.107.230', '162.19.255.78', '162.19.255.36', '162.19.255.224', '162.19.255.223', '162.19.254.244', '162.19.254.232', '162.19.254.230', '162.19.253.242', '162.19.249.48', '162.19.245.142', '162.19.231.20', '162.19.229.177', '162.19.228.128', '162.19.228.127', '162.19.228.105', '141.95.1.32', '141.95.1.196', '141.95.1.102', '141.95.0.50', '141.95.0.248', '135.125.237.84', '135.125.233.236']
\ No newline at end of file
diff --git a/Src/Api/Streamingcommunity/film.py b/Src/Api/Streamingcommunity/film.py
index 2b9d7bf..765a5cf 100644
--- a/Src/Api/Streamingcommunity/film.py
+++ b/Src/Api/Streamingcommunity/film.py
@@ -18,7 +18,7 @@ from .Core.Vix_player.player import VideoSource
# Config
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
-from .costant import STREAMING_FOLDER, MOVIE_FOLDER
+from .costant import STREAMING_FOLDER, MOVIE_FOLDER, STATIC_IP_SERVER
# Variable
@@ -59,4 +59,4 @@ def download_film(id_film: str, title_name: str, domain: str):
Downloader(
m3u8_playlist = master_playlist,
output_filename = os.path.join(mp4_path, mp4_format)
- ).start()
\ No newline at end of file
+ ).start(STATIC_IP_SERVER)
\ No newline at end of file
diff --git a/Src/Api/Streamingcommunity/series.py b/Src/Api/Streamingcommunity/series.py
index 9b2ecc0..1d0458b 100644
--- a/Src/Api/Streamingcommunity/series.py
+++ b/Src/Api/Streamingcommunity/series.py
@@ -20,7 +20,7 @@ from .Core.Util import manage_selection, map_episode_title
# Config
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
-from .costant import STREAMING_FOLDER, SERIES_FOLDER
+from .costant import STREAMING_FOLDER, SERIES_FOLDER, STATIC_IP_SERVER
# Variable
@@ -96,7 +96,7 @@ def donwload_video(tv_name: str, index_season_selected: int, index_episode_selec
Downloader(
m3u8_playlist = master_playlist,
output_filename = os.path.join(mp4_path, mp4_name)
- ).start()
+ ).start(STATIC_IP_SERVER)
def donwload_episode(tv_name: str, index_season_selected: int, donwload_all: bool = False) -> None:
diff --git a/Src/Lib/Hls/segments.py b/Src/Lib/Hls/segments.py
index fe2a131..8dfbf05 100644
--- a/Src/Lib/Hls/segments.py
+++ b/Src/Lib/Hls/segments.py
@@ -109,7 +109,7 @@ class M3U8_Segments:
logging.info(f"Key: ('hex': {hex_content}, 'byte': {byte_content})")
return byte_content
- def __test_ip(self):
+ def __test_ip(self, url_to_test: str):
"""
Tests each proxy IP by sending a request to a corresponding segment URL.
"""
@@ -117,16 +117,18 @@ class M3U8_Segments:
failed_ips = []
for i in range(len(self.fake_proxy_ip)):
- url_to_test = self.segments[i]
try:
+ response = requests.get(url_to_test, verify=False, retries=0)
+
+ if response == None:
+ logging.error(f"[Work] to make request using: {url_to_test}")
+ failed_ips.append(i)
- # Attempt to send a GET request to the URL
- requests.get(url_to_test, verify=self.verify_ssl)
except:
# Log the error and add the IP to the list of failed IPs
- logging.error(f"Failed to make request using IP in this request: {url_to_test}")
+ logging.error(f"[Fail] to make request using IP in this request: {url_to_test}")
failed_ips.append(i)
# Remove the failed IPs from the fake_proxy_ip list
@@ -134,8 +136,13 @@ class M3U8_Segments:
# Exit the program if 50% requests failed
if len(failed_ips) / 2 > len(self.fake_proxy_ip):
- logging.error("All requests with ip failed. Exiting the program.")
- sys.exit(0)
+ logging.error("All requests with ip failed.")
+
+ # Set to not use proxy
+ self.fake_proxy_ip = None
+ self.fake_proxy = False
+
+ return False
def parse_data(self, m3u8_content: str) -> None:
"""
@@ -182,10 +189,13 @@ class M3U8_Segments:
for i in range(len(self.segments)):
segment_url = self.segments[i]
- self.segments[i] = self.__gen_proxy__(segment_url, self.segments.index(segment_url))
+ # Set to not use proxy if 50% failed
+ if not self.__test_ip(segment_url):
+ console.log("[red]Cant use proxy switch to normal url.")
+ self.fake_proxy = False
+ break
- # Test new url with ip
- self.__test_ip()
+ self.segments[i] = self.__gen_proxy__(segment_url, self.segments.index(segment_url))
# Save new playlist of segment
path_m3u8_file = os.path.join(self.tmp_folder, "playlist_fix.m3u8")
@@ -226,12 +236,17 @@ class M3U8_Segments:
Returns:
str: The modified URL with the new IP address.
"""
- new_ip_address = self.fake_proxy_ip[url_index % len(self.fake_proxy_ip)]
+ if self.fake_proxy:
- # Parse the original URL and replace the hostname with the new IP address
- parsed_url = urlparse(url)._replace(netloc=new_ip_address)
+ new_ip_address = self.fake_proxy_ip[url_index % len(self.fake_proxy_ip)]
- return urlunparse(parsed_url)
+ # Parse the original URL and replace the hostname with the new IP address
+ parsed_url = urlparse(url)._replace(netloc=new_ip_address)
+
+ return urlunparse(parsed_url)
+
+ else:
+ return url
def make_requests_stream(self, ts_url: str, index: int, progress_bar: tqdm) -> None:
"""
From febc16b6de4e70d157e337a58791ef2cf8d51807 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Tue, 4 Jun 2024 23:20:55 +0200
Subject: [PATCH 12/13] Duplicate ip
---
Src/Api/Animeunity/anime.py | 4 ++--
Src/Api/Animeunity/costant.py | 2 --
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/Src/Api/Animeunity/anime.py b/Src/Api/Animeunity/anime.py
index 79a2355..26a6357 100644
--- a/Src/Api/Animeunity/anime.py
+++ b/Src/Api/Animeunity/anime.py
@@ -18,7 +18,7 @@ from .Core.Util import manage_selection
# Config
ROOT_PATH = config_manager.get('DEFAULT', 'root_path')
-from .costant import ANIME_FOLDER, SERIES_FOLDER, MOVIE_FOLDER, STATIC_IP_SERVER
+from .costant import ANIME_FOLDER, SERIES_FOLDER, MOVIE_FOLDER
# Variable
@@ -61,7 +61,7 @@ def download_episode(index_select: int):
)
# Start downloading
- obj_download.start(STATIC_IP_SERVER)
+ obj_download.start()
def donwload_series(tv_id: int, tv_name: str):
diff --git a/Src/Api/Animeunity/costant.py b/Src/Api/Animeunity/costant.py
index 28f0252..7e75bc2 100644
--- a/Src/Api/Animeunity/costant.py
+++ b/Src/Api/Animeunity/costant.py
@@ -3,5 +3,3 @@
ANIME_FOLDER = "animeunity"
SERIES_FOLDER= "Serie"
MOVIE_FOLDER = "Movie"
-
-STATIC_IP_SERVER = ['57.129.7.85', '57.129.7.188', '57.129.7.174', '57.129.4.77', '57.129.16.196', '57.129.16.156', '57.129.16.139', '57.129.16.135', '57.129.13.175', '57.129.13.157', '51.38.112.237', '51.195.107.7', '51.195.107.230', '162.19.255.78', '162.19.255.36', '162.19.255.224', '162.19.255.223', '162.19.254.244', '162.19.254.232', '162.19.254.230', '162.19.253.242', '162.19.249.48', '162.19.245.142', '162.19.231.20', '162.19.229.177', '162.19.228.128', '162.19.228.127', '162.19.228.105', '141.95.1.32', '141.95.1.196', '141.95.1.102', '141.95.0.50', '141.95.0.248', '135.125.237.84', '135.125.233.236']
\ No newline at end of file
From ae12d86d711274198680fe44ac690d960924fad9 Mon Sep 17 00:00:00 2001
From: Ghost <62809003+Ghost6446@users.noreply.github.com>
Date: Wed, 5 Jun 2024 23:29:35 +0200
Subject: [PATCH 13/13] Update library and remove my request and user agent.
---
.../Altadefinizione/Core/Player/supervideo.py | 5 +-
Src/Api/Altadefinizione/site.py | 2 +-
Src/Api/Animeunity/Core/Util/get_domain.py | 4 +-
Src/Api/Animeunity/Core/Vix_player/player.py | 2 +-
Src/Api/Animeunity/site.py | 2 +-
.../Core/Util/get_domain.py | 5 +-
.../Core/Vix_player/player.py | 2 +-
Src/Api/Streamingcommunity/site.py | 2 +-
Src/Lib/Google/page.py | 2 +-
Src/Lib/Hls/downloader.py | 2 +-
Src/Lib/Hls/segments.py | 12 +-
Src/Lib/M3U8/estimator.py | 9 +-
Src/Lib/M3U8/parser.py | 2 +-
Src/Lib/Request/__init__.py | 3 -
Src/Lib/Request/my_requests.py | 541 ------------------
Src/Lib/UserAgent/__init__.py | 3 -
Src/Lib/UserAgent/user_agent.py | 112 ----
Src/Upload/update.py | 2 +-
Src/Util/headers.py | 15 +-
Test/t_get_server_ip_sc.py | 3 +-
requirements.txt | 6 +-
21 files changed, 43 insertions(+), 693 deletions(-)
delete mode 100644 Src/Lib/Request/__init__.py
delete mode 100644 Src/Lib/Request/my_requests.py
delete mode 100644 Src/Lib/UserAgent/__init__.py
delete mode 100644 Src/Lib/UserAgent/user_agent.py
diff --git a/Src/Api/Altadefinizione/Core/Player/supervideo.py b/Src/Api/Altadefinizione/Core/Player/supervideo.py
index 9be0249..48e8155 100644
--- a/Src/Api/Altadefinizione/Core/Player/supervideo.py
+++ b/Src/Api/Altadefinizione/Core/Player/supervideo.py
@@ -1,15 +1,12 @@
# 26.05.24
import re
-import os
import sys
-import time
import logging
-import subprocess
# External libraries
-from Src.Lib.Request import requests
+import requests
from bs4 import BeautifulSoup
diff --git a/Src/Api/Altadefinizione/site.py b/Src/Api/Altadefinizione/site.py
index 958cc8d..1a53609 100644
--- a/Src/Api/Altadefinizione/site.py
+++ b/Src/Api/Altadefinizione/site.py
@@ -6,7 +6,7 @@ import logging
# External libraries
-from Src.Lib.Request import requests
+import requests
from bs4 import BeautifulSoup
from unidecode import unidecode
diff --git a/Src/Api/Animeunity/Core/Util/get_domain.py b/Src/Api/Animeunity/Core/Util/get_domain.py
index 36e02cd..6730179 100644
--- a/Src/Api/Animeunity/Core/Util/get_domain.py
+++ b/Src/Api/Animeunity/Core/Util/get_domain.py
@@ -5,8 +5,8 @@ import threading
import logging
-# Internal libraries
-from Src.Lib.Request import requests
+# External libraries
+import requests
# Internal utilities
diff --git a/Src/Api/Animeunity/Core/Vix_player/player.py b/Src/Api/Animeunity/Core/Vix_player/player.py
index bcac59a..c977888 100644
--- a/Src/Api/Animeunity/Core/Vix_player/player.py
+++ b/Src/Api/Animeunity/Core/Vix_player/player.py
@@ -6,7 +6,7 @@ from urllib.parse import urljoin, urlparse, parse_qs, urlencode, urlunparse
# External libraries
-from Src.Lib.Request import requests
+import requests
from bs4 import BeautifulSoup
diff --git a/Src/Api/Animeunity/site.py b/Src/Api/Animeunity/site.py
index 28ee558..b885afd 100644
--- a/Src/Api/Animeunity/site.py
+++ b/Src/Api/Animeunity/site.py
@@ -5,7 +5,7 @@ import logging
# External libraries
-from Src.Lib.Request import requests
+import requests
from bs4 import BeautifulSoup
from unidecode import unidecode
diff --git a/Src/Api/Streamingcommunity/Core/Util/get_domain.py b/Src/Api/Streamingcommunity/Core/Util/get_domain.py
index 0faada4..4017c43 100644
--- a/Src/Api/Streamingcommunity/Core/Util/get_domain.py
+++ b/Src/Api/Streamingcommunity/Core/Util/get_domain.py
@@ -5,8 +5,11 @@ import threading
import logging
+# External library
+import requests
+
+
# Internal utilities
-from Src.Lib.Request import requests
from Src.Lib.Google import search as google_search
diff --git a/Src/Api/Streamingcommunity/Core/Vix_player/player.py b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
index bd72041..cb26be4 100644
--- a/Src/Api/Streamingcommunity/Core/Vix_player/player.py
+++ b/Src/Api/Streamingcommunity/Core/Vix_player/player.py
@@ -6,7 +6,7 @@ from urllib.parse import urljoin, urlparse, parse_qs, urlencode, urlunparse
# External libraries
-from Src.Lib.Request import requests
+import requests
from bs4 import BeautifulSoup
diff --git a/Src/Api/Streamingcommunity/site.py b/Src/Api/Streamingcommunity/site.py
index 606e77c..bdd5ec9 100644
--- a/Src/Api/Streamingcommunity/site.py
+++ b/Src/Api/Streamingcommunity/site.py
@@ -8,12 +8,12 @@ from typing import Tuple
# External libraries
+import requests
from bs4 import BeautifulSoup
from unidecode import unidecode
# Internal utilities
-from Src.Lib.Request import requests
from Src.Util.headers import get_headers
from Src.Util._jsonConfig import config_manager
from Src.Util.console import console
diff --git a/Src/Lib/Google/page.py b/Src/Lib/Google/page.py
index 2185ad7..54e976f 100644
--- a/Src/Lib/Google/page.py
+++ b/Src/Lib/Google/page.py
@@ -8,7 +8,7 @@ from typing import Generator, Optional
# External libraries
-from Src.Lib.Request import requests
+import requests
from bs4 import BeautifulSoup
diff --git a/Src/Lib/Hls/downloader.py b/Src/Lib/Hls/downloader.py
index 9ef3ff3..26bd443 100644
--- a/Src/Lib/Hls/downloader.py
+++ b/Src/Lib/Hls/downloader.py
@@ -8,7 +8,7 @@ from concurrent.futures import ThreadPoolExecutor
# External libraries
-from Src.Lib.Request import requests
+import requests
from unidecode import unidecode
diff --git a/Src/Lib/Hls/segments.py b/Src/Lib/Hls/segments.py
index 8dfbf05..050706e 100644
--- a/Src/Lib/Hls/segments.py
+++ b/Src/Lib/Hls/segments.py
@@ -12,7 +12,7 @@ from urllib.parse import urljoin, urlparse, urlunparse
# External libraries
-from Src.Lib.Request import requests
+import requests
from tqdm import tqdm
@@ -22,6 +22,7 @@ from Src.Util.headers import get_headers
from Src.Util.color import Colors
from Src.Util._jsonConfig import config_manager
+
# Logic class
from ..M3U8 import (
M3U8_Decryption,
@@ -30,6 +31,11 @@ from ..M3U8 import (
M3U8_UrlFix
)
+
+# Warning
+import urllib3
+urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
# Config
TQDM_MAX_WORKER = config_manager.get_int('M3U8_DOWNLOAD', 'tdqm_workers')
TQDM_USE_LARGE_BAR = config_manager.get_int('M3U8_DOWNLOAD', 'tqdm_use_large_bar')
@@ -265,7 +271,7 @@ class M3U8_Segments:
# Make request and calculate time duration
start_time = time.time()
- response = requests.get(ts_url, headers=headers_segments, verify=REQUEST_VERIFY_SSL, timeout=30)
+ response = requests.get(ts_url, headers=headers_segments, verify=REQUEST_VERIFY_SSL, timeout=15)
duration = time.time() - start_time
logging.info(f"Make request to get segment: [{index} - {len(self.segments)}] in: {duration}, len data: {len(response.content)}")
@@ -275,7 +281,7 @@ class M3U8_Segments:
segment_content = response.content
# Update bar
- self.class_ts_estimator.update_progress_bar(segment_content, duration, progress_bar)
+ self.class_ts_estimator.update_progress_bar(int(response.headers.get('Content-Length', 0)), duration, progress_bar)
# Decrypt the segment content if decryption is needed
if self.decryption is not None:
diff --git a/Src/Lib/M3U8/estimator.py b/Src/Lib/M3U8/estimator.py
index e0e6596..e762a40 100644
--- a/Src/Lib/M3U8/estimator.py
+++ b/Src/Lib/M3U8/estimator.py
@@ -31,7 +31,7 @@ class M3U8_Ts_Estimator:
"""
self.ts_file_sizes = []
self.now_downloaded_size = 0
- self.average_over = 6
+ self.average_over = 3
self.list_speeds = deque(maxlen=self.average_over)
self.smoothed_speeds = []
self.total_segments = total_segments
@@ -52,7 +52,7 @@ class M3U8_Ts_Estimator:
# Calculate speed outside of the lock
try:
- speed_mbps = (size_download * 16) / (duration * 1_000_000)
+ speed_mbps = (size_download * 8) / (duration * 1_000_000)
except ZeroDivisionError as e:
logging.error("Division by zero error while calculating speed: %s", e)
return
@@ -114,16 +114,15 @@ class M3U8_Ts_Estimator:
"""
return format_size(self.now_downloaded_size)
- def update_progress_bar(self, segment_content: bytes, duration: float, progress_counter: tqdm) -> None:
+ def update_progress_bar(self, total_downloaded: int, duration: float, progress_counter: tqdm) -> None:
"""
Updates the progress bar with information about the TS segment download.
Args:
- segment_content (bytes): The content of the downloaded TS segment.
+ total_downloaded (int): The len of the content of the downloaded TS segment.
duration (float): The duration of the segment download in seconds.
progress_counter (tqdm): The tqdm object representing the progress bar.
"""
- total_downloaded = len(segment_content)
# Add the size of the downloaded segment to the estimator
self.add_ts_file(total_downloaded * self.total_segments, total_downloaded, duration)
diff --git a/Src/Lib/M3U8/parser.py b/Src/Lib/M3U8/parser.py
index a29a82f..bf364eb 100644
--- a/Src/Lib/M3U8/parser.py
+++ b/Src/Lib/M3U8/parser.py
@@ -8,7 +8,7 @@ from .lib_parser import load
# External libraries
-from Src.Lib.Request import requests
+import requests
# Costant
diff --git a/Src/Lib/Request/__init__.py b/Src/Lib/Request/__init__.py
deleted file mode 100644
index f6af28d..0000000
--- a/Src/Lib/Request/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# 04.4.24
-
-from .my_requests import requests
\ No newline at end of file
diff --git a/Src/Lib/Request/my_requests.py b/Src/Lib/Request/my_requests.py
deleted file mode 100644
index 405d892..0000000
--- a/Src/Lib/Request/my_requests.py
+++ /dev/null
@@ -1,541 +0,0 @@
-# 04.4.24
-
-import os
-import sys
-import base64
-import json
-import logging
-import ssl
-import time
-import re
-import subprocess
-import urllib.parse
-import urllib.request
-import urllib.error
-
-from typing import Dict, Optional, Union, Any
-
-
-try:
- from typing import Unpack, TypedDict
-except ImportError:
- # (Python <= 3.10),
- try:
- from typing_extensions import Unpack, TypedDict # type: ignore
- except ImportError:
- raise ImportError("Unable to import Unpack from typing or typing_extensions. "
- "Please make sure you have the necessary libraries installed.")
-
-
-# External library
-from bs4 import BeautifulSoup
-
-
-# Internal utilities
-from Src.Util._jsonConfig import config_manager
-
-
-# Default settings
-HTTP_TIMEOUT = config_manager.get_int('REQUESTS', 'timeout')
-HTTP_RETRIES = config_manager.get_int('REQUESTS', 'max_retry')
-HTTP_DELAY = 1
-
-
-
-class RequestError(Exception):
- """Custom exception class for request errors."""
-
- def __init__(self, message: str, original_exception: Optional[Exception] = None) -> None:
- """
- Initialize a RequestError instance.
-
- Args:
- - message (str): The error message.
- - original_exception (Optional[Exception], optional): The original exception that occurred. Defaults to None.
- """
- super().__init__(message)
- self.original_exception = original_exception
-
- def __str__(self) -> str:
- """Return a string representation of the exception."""
- if self.original_exception:
- return f"{super().__str__()} Original Exception: {type(self.original_exception).__name__}: {str(self.original_exception)}"
- else:
- return super().__str__()
-
-
-def parse_http_error(error_string: str):
- """
- Parse the HTTP error string to extract the error code and message.
-
- Args:
- - error_string (str): The error string from an HTTP response.
-
- Returns:
- dict: A dictionary with 'error_code' and 'message' if the string is parsed successfully, or None if parsing fails.
- """
-
- # Regular expression to match the error pattern
- error_pattern = re.compile(r"HTTP Error (\d{3}): (.+)")
- match = error_pattern.search(error_string)
-
- if match:
- error_code = match.group(1)
- message = match.group(2)
- return {'error_code': error_code, 'message': message}
-
- else:
- logging.error(f"Error string does not match expected format: {error_string}")
- return None
-
-
-class Response:
- """
- Class representing an HTTP response.
- """
- def __init__(
- self,
- status: int,
- text: str,
- is_json: bool = False,
- content: bytes = b"",
- headers: Optional[Dict[str, str]] = None,
- cookies: Optional[Dict[str, str]] = None,
- redirect_url: Optional[str] = None,
- response_time: Optional[float] = None,
- timeout: Optional[float] = None,
- ):
- """
- Initialize a Response object.
-
- Args:
- - status (int): The HTTP status code of the response.
- - text (str): The response content as text.
- - is_json (bool, optional): Indicates if the response content is JSON. Defaults to False.
- - content (bytes, optional): The response content as bytes. Defaults to b"".
- - headers (Optional[Dict[str, str]], optional): The response headers. Defaults to None.
- - cookies (Optional[Dict[str, str]], optional): The cookies set in the response. Defaults to None.
- - redirect_url (Optional[str], optional): The URL if a redirection occurred. Defaults to None.
- - response_time (Optional[float], optional): The time taken to receive the response. Defaults to None.
- - timeout (Optional[float], optional): The request timeout. Defaults to None.
- """
- self.status_code = status
- self.text = text
- self.is_json = is_json
- self.content = content
- self.headers = headers or {}
- self.cookies = cookies or {}
- self.redirect_url = redirect_url
- self.response_time = response_time
- self.timeout = timeout
- self.ok = 200 <= status < 300
-
- def raise_for_status(self):
- """
- Raise an error if the response status code is not in the 2xx range.
- """
- if not self.ok:
- raise RequestError(f"Request failed with status code {self.status_code}")
-
- def json(self):
- """
- Return the response content as JSON if it is JSON.
-
- Returns:
- dict or list or None: A Python dictionary or list parsed from JSON if the response content is JSON, otherwise None.
- """
- if self.is_json:
- return json.loads(self.text)
- else:
- return None
-
- def get_redirects(self):
- """
- Extracts unique site URLs from HTML elements within the section.
-
- Returns:
- list or None: A list of unique site URLs if found, otherwise None.
- """
-
- site_find = []
-
- if self.text:
- soup = BeautifulSoup(self.text, "html.parser")
-
- for links in soup.find("head").find_all('link'):
- if links is not None:
- parsed_url = urllib.parse.urlparse(links.get('href'))
- site = parsed_url.scheme + "://" + parsed_url.netloc
-
- if site not in site_find:
- site_find.append(site)
-
- if site_find:
- return site_find
- else:
- return None
-
-
-class ManageRequests:
- """
- Class for managing HTTP requests.
- """
- def __init__(
- self,
- url: str,
- method: str = 'GET',
- headers: Optional[Dict[str, str]] = None,
- timeout: float = HTTP_TIMEOUT,
- retries: int = HTTP_RETRIES,
- params: Optional[Dict[str, str]] = None,
- verify: bool = True,
- auth: Optional[tuple] = None,
- proxy: Optional[str] = None,
- cookies: Optional[Dict[str, str]] = None,
- json_data: Optional[Dict[str, Any]] = None,
- redirection_handling: bool = True,
- ):
- """
- Initialize a ManageRequests object.
-
- Args:
- - url (str): The URL to which the request will be sent.
- - method (str, optional): The HTTP method to be used for the request. Defaults to 'GET'.
- - headers (Optional[Dict[str, str]], optional): The request headers. Defaults to None.
- - timeout (float, optional): The request timeout. Defaults to HTTP_TIMEOUT.
- - retries (int, optional): The number of retries in case of request failure. Defaults to HTTP_RETRIES.
- - params (Optional[Dict[str, str]], optional): The query parameters for the request. Defaults to None.
- - verify (bool, optional): Indicates whether SSL certificate verification should be performed. Defaults to True.
- - auth (Optional[tuple], optional): Tuple containing the username and password for basic authentication. Defaults to None.
- - proxy (Optional[str], optional): The proxy URL. Defaults to None.
- - cookies (Optional[Dict[str, str]], optional): The cookies to be included in the request. Defaults to None.
- - redirection_handling (bool, optional): Indicates whether redirections should be followed. Defaults to True.
- """
- self.url = url
- self.method = method
- self.headers = headers or {}
- self.timeout = timeout
- self.retries = retries
- self.params = params
- self.verify_ssl = verify
- self.auth = auth
- self.proxy = proxy
- self.cookies = cookies
- self.json_data = json_data
- self.redirection_handling = redirection_handling
-
- def add_header(self, key: str, value: str) -> None:
- """
- Add a header to the request.
- """
- self.headers[key] = value
-
- def send(self) -> Response:
- """
- Send the HTTP request.
- """
-
- start_time = time.time()
- self.attempt = 0
- redirect_url = None
-
- while self.attempt < self.retries:
- try:
- req = self._build_request()
- response = self._perform_request(req)
-
- return self._process_response(response, start_time, redirect_url)
-
- except (urllib.error.URLError, urllib.error.HTTPError) as e:
- self._handle_error(e)
- self.attempt += 1
-
- def log_request(self):
- """
- Constructs a log message based on the request parameters and logs it.
- """
- log_message = "Request: ("
-
- if self.url:
- log_message += f"'url': {self.url}, "
- if self.headers:
- log_message += f"'headers': {self.headers}, "
- if self.cookies:
- log_message += f"'cookies': {self.cookies}, "
- if self.json_data:
- log_message += f"'body': {json.dumps(self.json_data).encode('utf-8')}, "
-
- # Remove the trailing comma and add parentheses
- log_message = log_message.rstrip(", ") + ")"
- logging.info(log_message)
-
- def _build_request(self) -> urllib.request.Request:
- """
- Build the urllib Request object.
- """
-
- # Make a copy of headers to avoid modifying the original dictionary
- headers = self.headers.copy()
-
- # Construct the URL with query parameters if present
- if self.params:
- url = self.url + '?' + urllib.parse.urlencode(self.params)
- else:
- url = self.url
-
- # Create the initial Request object
- req = urllib.request.Request(url, headers=headers, method=self.method)
-
- # Add JSON data if provided
- if self.json_data:
- req.add_header('Content-Type', 'application/json')
- req.data = json.dumps(self.json_data).encode('utf-8')
-
- # Add authorization header if provided
- if self.auth:
- req.add_header('Authorization', 'Basic ' + base64.b64encode(f"{self.auth[0]}:{self.auth[1]}".encode()).decode())
-
- # Add cookies if provided
- if self.cookies:
- cookie_str = '; '.join([f"{name}={value}" for name, value in self.cookies.items()])
- req.add_header('Cookie', cookie_str)
-
- # Add default user agent if not already present
- if 'user-agent' not in headers:
- default_user_agent = 'Mozilla/5.0'
- req.add_header('user-agent', default_user_agent)
-
-
- self.log_request()
- return req
-
- def _perform_request(self, req: urllib.request.Request) -> urllib.response.addinfourl:
- """
- Perform the HTTP request.
- """
- if self.proxy:
- proxy_handler = urllib.request.ProxyHandler({'http': self.proxy, 'https': self.proxy})
- opener = urllib.request.build_opener(proxy_handler)
- urllib.request.install_opener(opener)
-
- if not self.verify_ssl:
-
- # Create SSL context
- ssl_context = ssl.create_default_context()
- ssl_context.check_hostname = False
- ssl_context.verify_mode = ssl.CERT_NONE
-
- # Build the request with SSL context
- response = urllib.request.urlopen(req, timeout=self.timeout, context=ssl_context)
-
- else:
- response = urllib.request.urlopen(req, timeout=self.timeout, context=ssl.create_default_context())
-
- return response
-
- def _process_response(self, response: urllib.response.addinfourl, start_time: float, redirect_url: Optional[str]) -> Response:
- """
- Process the HTTP response.
- """
- response_data = response.read()
- content_type = response.headers.get('Content-Type', '').lower()
-
- if self.redirection_handling and response.status in (301, 302, 303, 307, 308):
- location = response.headers.get('Location')
- logging.info(f"Redirecting to: {location}")
- redirect_url = location
- self.url = location
- return self.send()
-
- return self._build_response(response, response_data, start_time, redirect_url, content_type)
-
- def _build_response(self, response: urllib.response.addinfourl, response_data: bytes, start_time: float, redirect_url: Optional[str], content_type: str) -> Response:
- """
- Build the Response object.
- """
- response_time = time.time() - start_time
- response_headers = dict(response.headers)
- response_cookies = {}
-
- for cookie in response.headers.get_all('Set-Cookie', []):
- cookie_parts = cookie.split(';')
- cookie_name, cookie_value = cookie_parts[0].split('=', 1) # Only the first
- response_cookies[cookie_name.strip()] = cookie_value.strip()
-
- return Response(
- status=response.status,
- text=response_data.decode('latin-1'),
- is_json=("json" in content_type),
- content=response_data,
- headers=response_headers,
- cookies=response_cookies,
- redirect_url=redirect_url,
- response_time=response_time,
- timeout=self.timeout,
- )
-
- def _handle_error(self, e: Union[urllib.error.URLError, urllib.error.HTTPError]) -> None:
- """
- Handle request error.
- """
- logging.error(f"Request failed for URL '{self.url}': {parse_http_error(str(e))}")
-
- if self.attempt < self.retries:
- logging.error(f"Retry request for URL '{self.url}' (attempt {self.attempt}/{self.retries})")
- time.sleep(HTTP_DELAY)
-
- else:
- logging.error(f"Maximum retries reached for URL '{self.url}'")
- raise RequestError(str(e))
-
-
-class ValidateRequest:
- """
- Class for validating request inputs.
- """
- @staticmethod
- def validate_url(url: str) -> bool:
- """Validate URL format."""
-
- url_regex = re.compile(
- r'^(?:http|ftp)s?://' # http:// or https://
- r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' # domain...
- r'localhost|' # localhost...
- r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', re.IGNORECASE)
- return re.match(url_regex, url) is not None
-
- @staticmethod
- def validate_headers(headers: Dict[str, str]) -> bool:
- """Validate header values."""
-
- for key, value in headers.items():
- if not isinstance(key, str) or not isinstance(value, str):
- return False
- return True
-
-
-class ValidateResponse:
- """
- Class for validating response data.
- """
- @staticmethod
- def is_valid_json(data: str) -> bool:
- """Check if response data is a valid JSON."""
-
- try:
- json.loads(data)
- return True
- except ValueError:
- return False
-
-
-class SSLHandler:
- """Class for handling SSL certificates."""
- @staticmethod
- def load_certificate(custom_cert_path: str) -> None:
- """Load custom SSL certificate."""
- ssl_context = ssl.create_default_context(cafile=custom_cert_path)
- ssl_context.check_hostname = False
- ssl_context.verify_mode = ssl.CERT_NONE
-
-
-class KwargsRequest(TypedDict, total = False):
- url: str
- headers: Optional[Dict[str, str]] = None
- timeout: float = HTTP_TIMEOUT
- retries: int = HTTP_RETRIES
- params: Optional[Dict[str, str]] = None
- cookies: Optional[Dict[str, str]] = None
- verify_ssl: bool = True
- json_data: Optional[Dict[str, Any]] = None
-
-
-class Request:
- """
- Class for making HTTP requests.
- """
- def __init__(self) -> None:
-
- # Ensure SSL certificate is set up
- self.__setup_ssl_certificate__()
-
- def __setup_ssl_certificate__(self):
- """
- Set up SSL certificate environment variables.
- """
- try:
- # Determine the Python executable
- python_executable = sys.executable
- logging.info("Python path: ", python_executable)
-
- # Check if certifi package is installed, install it if not
- if subprocess.run([python_executable, "-c", "import certifi"], capture_output=True).returncode != 0:
- subprocess.run(["pip", "install", "certifi"], check=True)
- logging.info("Installed certifi package.")
-
- # Get path to SSL certificate
- cert_path = subprocess.run([python_executable, "-c", "import certifi; print(certifi.where())"], capture_output=True, text=True, check=True).stdout.strip()
- logging.info("Path cert: ", cert_path)
-
- if not cert_path:
- raise ValueError("Unable to determine the path to the SSL certificate.")
-
- # Set SSL certificate environment variables
- os.environ['SSL_CERT_FILE'] = cert_path
- os.environ['REQUESTS_CA_BUNDLE'] = cert_path
-
- except subprocess.CalledProcessError as e:
- raise ValueError(f"Error executing subprocess: {e}") from e
-
- def get(self, url: str, **kwargs: Unpack[KwargsRequest])-> 'Response':
- """
- Send a GET request.
-
- Args:
- - url (str): The URL to which the request will be sent.
- **kwargs: Additional keyword arguments for the request.
-
- Returns:
- Response: The response object.
- """
- return self._send_request(url, 'GET', **kwargs)
-
- def post(self, url: str, **kwargs: Unpack[KwargsRequest]) -> 'Response':
- """
- Send a POST request.
-
- Args:
- - url (str): The URL to which the request will be sent.
- **kwargs: Additional keyword arguments for the request.
-
- Returns:
- Response: The response object.
- """
- return self._send_request(url, 'POST', **kwargs)
-
- def head(self, url: str, **kwargs: Unpack[KwargsRequest]) -> 'Response':
- """
- Send a HEAD request.
-
- Args:
- - url (str): The URL to which the request will be sent.
- **kwargs: Additional keyword arguments for the request.
-
- Returns:
- Response: The response object.
- """
- return self._send_request(url, 'HEAD', **kwargs)
-
- def _send_request(self, url: str, method: str, **kwargs: Unpack[KwargsRequest]) -> 'Response':
- """Send an HTTP request."""
- if not ValidateRequest.validate_url(url):
- raise ValueError("Invalid URL format")
-
- if 'headers' in kwargs and not ValidateRequest.validate_headers(kwargs['headers']):
- raise ValueError("Invalid header values")
-
- return ManageRequests(url, method, **kwargs).send()
-
-
-# Output
-requests: Request = Request()
\ No newline at end of file
diff --git a/Src/Lib/UserAgent/__init__.py b/Src/Lib/UserAgent/__init__.py
deleted file mode 100644
index b90fa6e..0000000
--- a/Src/Lib/UserAgent/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# 04.4.24
-
-from .user_agent import ua
\ No newline at end of file
diff --git a/Src/Lib/UserAgent/user_agent.py b/Src/Lib/UserAgent/user_agent.py
deleted file mode 100644
index b7c5b74..0000000
--- a/Src/Lib/UserAgent/user_agent.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# 04.4.24
-
-import logging
-import re
-import os
-import random
-import threading
-import json
-import tempfile
-
-from typing import Dict, List
-
-
-# Internal libraries
-from Src.Lib.Request import requests
-
-
-
-def get_browser_user_agents_online(browser: str) -> List[str]:
- """
- Retrieve browser user agent strings from a website.
-
- Args:
- - browser (str): The name of the browser (e.g., 'chrome', 'firefox', 'safari').
-
- Returns:
- List[str]: List of user agent strings for the specified browser.
- """
- url = f"https://useragentstring.com/pages/{browser}/"
-
- try:
-
- # Make request and find all user agents
- html = requests.get(url).text
- browser_user_agents = re.findall(r"(.+?)", html, re.UNICODE)
- return [ua for ua in browser_user_agents if "more" not in ua.lower()]
-
- except Exception as e:
- logging.error(f"Failed to fetch user agents for '{browser}': {str(e)}")
- return []
-
-
-def update_user_agents(browser_name: str, browser_user_agents: Dict[str, List[str]]) -> None:
- """
- Update browser user agents dictionary with new requests.
-
- Args:
- - browser_name (str): Name of the browser.
- - browser_user_agents (Dict[str, List[str]]): Dictionary to store browser user agents.
- """
- browser_user_agents[browser_name] = get_browser_user_agents_online(browser_name)
-
-
-def create_or_update_user_agent_file() -> None:
- """
- Create or update the user agent file with browser user agents.
- """
- user_agent_file = os.path.join(tempfile.gettempdir(), 'fake_user_agent.json')
- logging.info(f"Upload file: {user_agent_file}")
-
- if not os.path.exists(user_agent_file):
- browser_user_agents: Dict[str, List[str]] = {}
- threads = []
-
- for browser_name in ['chrome', 'firefox', 'safari']:
- t = threading.Thread(target=update_user_agents, args=(browser_name, browser_user_agents))
- threads.append(t)
- t.start()
-
- for t in threads:
- t.join()
-
- with open(user_agent_file, 'w') as f:
- json.dump(browser_user_agents, f, indent=4)
- logging.info(f"User agent file created at: {user_agent_file}")
-
- else:
- logging.info("User agent file already exists.")
-
-
-class UserAgentManager:
- """
- Manager class to access browser user agents from a file.
- """
- def __init__(self):
-
- # Get path to temp file where save all user agents
- self.user_agent_file = os.path.join(tempfile.gettempdir(), 'fake_user_agent.json')
- logging.info(f"Check file: {self.user_agent_file}")
-
- # If file dont exist, creaet it
- if not os.path.exists(self.user_agent_file):
- create_or_update_user_agent_file()
- logging.info(f"Create file: {self.user_agent_file}")
-
- def get_random_user_agent(self, browser: str) -> str:
- """
- Get a random user agent for the specified browser.
-
- Args:
- browser (str): The name of the browser ('chrome', 'firefox', 'safari').
-
- Returns:
- Optional[str]: Random user agent string for the specified browser.
- """
- with open(self.user_agent_file, 'r') as f:
- browser_user_agents = json.load(f)
- return random.choice(browser_user_agents.get(browser.lower(), []))
-
-
-# Output
-ua: UserAgentManager = UserAgentManager()
\ No newline at end of file
diff --git a/Src/Upload/update.py b/Src/Upload/update.py
index 7c6e4fa..6e3e543 100644
--- a/Src/Upload/update.py
+++ b/Src/Upload/update.py
@@ -10,7 +10,7 @@ from Src.Util.console import console
# External library
-from Src.Lib.Request import requests
+import requests
# Variable
diff --git a/Src/Util/headers.py b/Src/Util/headers.py
index ca76388..b84f4e9 100644
--- a/Src/Util/headers.py
+++ b/Src/Util/headers.py
@@ -3,8 +3,12 @@
import logging
-# Internal utilities
-from Src.Lib.UserAgent import ua
+# External library
+import fake_useragent
+
+
+# Variable
+useragent = fake_useragent.UserAgent()
def get_headers() -> str:
@@ -12,11 +16,8 @@ def get_headers() -> str:
Generate a random user agent to use in HTTP requests.
Returns:
- str: A random user agent string.
+ - str: A random user agent string.
"""
# Get a random user agent string from the user agent rotator
- random_headers = ua.get_random_user_agent("firefox")
-
- #logging.info(f"Use headers: {random_headers}")
- return random_headers
\ No newline at end of file
+ return useragent.firefox
\ No newline at end of file
diff --git a/Test/t_get_server_ip_sc.py b/Test/t_get_server_ip_sc.py
index 02bebe8..d89ebac 100644
--- a/Test/t_get_server_ip_sc.py
+++ b/Test/t_get_server_ip_sc.py
@@ -11,7 +11,7 @@ warnings.filterwarnings("ignore", category=urllib3.exceptions.InsecureRequestWar
# Variable
-url_test = "https://sc-b1-18.scws-content.net/hls/170/3/25/32503b5b-4646-4376-ad47-7766c65be7e2/audio/ita/0004-0100.ts"
+url_test = "https://sc-b1-18.scws-content.net/hls/100/b/d3/bd3a430d-0a13-4bec-8fcc-ea41af183555/audio/ita/0010-0100.ts?token=CiEPTIyvEoTkGk3szgDu9g&expires=1722801022"
def get_ip_from_url(url):
@@ -81,5 +81,6 @@ def main():
print(f"Valid IP addresses: {sorted(valid_ip, reverse=True)}")
+
if __name__ == '__main__':
main()
diff --git a/requirements.txt b/requirements.txt
index 3f1f64e..d9a07e1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,7 @@
-bs4
+requests
+bs4
certifi
tqdm
rich
-unidecode
\ No newline at end of file
+unidecode
+fake-useragent
\ No newline at end of file