update alldebrid plugin

This commit is contained in:
2026-05-23 14:20:12 -07:00
parent a8cdd09e1e
commit 6c0a1b4415
3 changed files with 146 additions and 142 deletions
+16 -1
View File
@@ -1460,6 +1460,8 @@ class Download_File(Cmdlet):
) -> List[Dict[str, Any]]: ) -> List[Dict[str, Any]]:
if not canonical_url: if not canonical_url:
return [] return []
if not cls._supports_storage_duplicate_lookup(canonical_url):
return []
config_dict = config if isinstance(config, dict) else {} config_dict = config if isinstance(config, dict) else {}
refs: List[Dict[str, Any]] = [] refs: List[Dict[str, Any]] = []
@@ -1691,6 +1693,20 @@ class Download_File(Cmdlet):
return storage, hydrus_available return storage, hydrus_available
@staticmethod
def _supports_storage_duplicate_lookup(raw_url: str) -> bool:
text = str(raw_url or "").strip()
if not text:
return False
try:
parsed = urlparse(text)
except Exception:
parsed = None
scheme = str(getattr(parsed, "scheme", "") or "").strip().lower()
return scheme in {"http", "https", "ftp", "ftps"}
@staticmethod @staticmethod
def _filter_supported_urls(raw_urls: Sequence[str]) -> tuple[List[str], List[str]]: def _filter_supported_urls(raw_urls: Sequence[str]) -> tuple[List[str], List[str]]:
"""Split explicit URLs into supported and unsupported buckets.""" """Split explicit URLs into supported and unsupported buckets."""
@@ -2690,7 +2706,6 @@ class Download_File(Cmdlet):
self._maybe_render_download_details(config=config) self._maybe_render_download_details(config=config)
return 0 return 0
log("No downloads completed", file=sys.stderr)
return 1 return 1
except Exception as e: except Exception as e:
+111 -99
View File
@@ -5,7 +5,6 @@ import json
import re import re
import sys import sys
import time import time
import shutil
import tempfile import tempfile
from pathlib import Path from pathlib import Path
from typing import Any, Dict, Iterable, List, Optional, Callable, Tuple from typing import Any, Dict, Iterable, List, Optional, Callable, Tuple
@@ -17,10 +16,12 @@ from PluginCore.base import Provider, SearchResult
from SYS.plugin_helpers import TablePluginMixin from SYS.plugin_helpers import TablePluginMixin
from SYS.item_accessors import get_field as _extract_value from SYS.item_accessors import get_field as _extract_value
from SYS.utils import sanitize_filename from SYS.utils import sanitize_filename
from SYS.logger import log, debug, debug_panel from SYS.logger import log
from SYS.models import DownloadError, PipeObject from SYS.models import DownloadError, PipeObject
_HOSTS_CACHE_TTL_SECONDS = 24 * 60 * 60 _HOSTS_CACHE_TTL_SECONDS = 24 * 60 * 60
_RUNTIME_HOSTS_PAYLOAD: Optional[Dict[str, Any]] = None
_RUNTIME_HOSTS_FETCHED_AT: float = 0.0
def _plugin_dir() -> Path: def _plugin_dir() -> Path:
@@ -61,18 +62,39 @@ def _resolve_hosts_cache_path() -> Path:
for legacy in _legacy_hosts_cache_paths(): for legacy in _legacy_hosts_cache_paths():
try: try:
if not legacy.exists() or not legacy.is_file(): if legacy.exists() and legacy.is_file():
continue return legacy
path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(legacy, path)
return path
except Exception: except Exception:
continue continue
return path return path
def _runtime_hosts_payload_is_fresh() -> bool:
if not isinstance(_RUNTIME_HOSTS_PAYLOAD, dict) or not _RUNTIME_HOSTS_PAYLOAD:
return False
try:
return (time.time() - float(_RUNTIME_HOSTS_FETCHED_AT)) < _HOSTS_CACHE_TTL_SECONDS
except Exception:
return False
def _load_hosts_payload() -> Optional[Dict[str, Any]]:
if _runtime_hosts_payload_is_fresh():
return _RUNTIME_HOSTS_PAYLOAD
path = _resolve_hosts_cache_path()
try:
if not path.exists() or not path.is_file():
return None
payload = json.loads(path.read_text(encoding="utf-8"))
except Exception:
return None
return payload if isinstance(payload, dict) else None
def _load_cached_domains(category: str) -> List[str]: def _load_cached_domains(category: str) -> List[str]:
"""Load cached domain list from the plugin-local alldebrid.json cache. """Load domain list from the runtime cache or bundled alldebrid.json snapshot.
category: "hosts" | "streams" | "redirectors" category: "hosts" | "streams" | "redirectors"
""" """
@@ -81,14 +103,7 @@ def _load_cached_domains(category: str) -> List[str]:
if wanted not in {"hosts", "streams", "redirectors"}: if wanted not in {"hosts", "streams", "redirectors"}:
return [] return []
path = _resolve_hosts_cache_path() payload = _load_hosts_payload()
try:
if not path.exists() or not path.is_file():
return []
payload = json.loads(path.read_text(encoding="utf-8"))
except Exception:
return []
if not isinstance(payload, dict): if not isinstance(payload, dict):
return [] return []
@@ -149,29 +164,6 @@ def _load_cached_hoster_domains() -> List[str]:
return _load_cached_domains("hosts") return _load_cached_domains("hosts")
def _save_cached_hosts_payload(payload: Dict[str, Any]) -> None:
path = _hosts_cache_path()
try:
path.parent.mkdir(parents=True, exist_ok=True)
except Exception:
return
try:
path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
except Exception:
return
def _cache_is_fresh() -> bool:
path = _resolve_hosts_cache_path()
try:
if not path.exists() or not path.is_file():
return False
mtime = float(path.stat().st_mtime)
return (time.time() - mtime) < _HOSTS_CACHE_TTL_SECONDS
except Exception:
return False
def _fetch_hosts_payload_v4_hosts() -> Optional[Dict[str, Any]]: def _fetch_hosts_payload_v4_hosts() -> Optional[Dict[str, Any]]:
"""Fetch the public AllDebrid hosts payload. """Fetch the public AllDebrid hosts payload.
@@ -192,13 +184,16 @@ def _fetch_hosts_payload_v4_hosts() -> Optional[Dict[str, Any]]:
def refresh_alldebrid_hoster_cache(*, force: bool = False) -> None: def refresh_alldebrid_hoster_cache(*, force: bool = False) -> None:
"""Refresh the on-disk cache of host domains (best-effort).""" """Refresh the in-memory host-domain cache for the current process."""
if (not force) and _cache_is_fresh(): global _RUNTIME_HOSTS_PAYLOAD, _RUNTIME_HOSTS_FETCHED_AT
if (not force) and _runtime_hosts_payload_is_fresh():
return return
payload = _fetch_hosts_payload_v4_hosts() payload = _fetch_hosts_payload_v4_hosts()
if isinstance(payload, dict) and payload: if isinstance(payload, dict) and payload:
_save_cached_hosts_payload(payload) _RUNTIME_HOSTS_PAYLOAD = payload
_RUNTIME_HOSTS_FETCHED_AT = time.time()
def _get_debrid_api_key(config: Dict[str, Any]) -> Optional[str]: def _get_debrid_api_key(config: Dict[str, Any]) -> Optional[str]:
@@ -387,39 +382,69 @@ def _looks_like_torrent_source(candidate: str) -> bool:
return False return False
def _dispatch_alldebrid_magnet_search( def _build_queued_magnet_item(
*,
magnet_spec: str,
magnet_id: int, magnet_id: int,
config: Dict[str, Any], magnet_info: Dict[str, Any],
) -> None: ) -> Dict[str, Any]:
try: title = str(
from cmdlet.file.search import CMDLET as _SEARCH_FILE_CMDLET magnet_info.get("filename")
or magnet_info.get("name")
or magnet_info.get("hash")
or f"magnet-{magnet_id}"
).strip() or f"magnet-{magnet_id}"
status_label = str(magnet_info.get("status") or "queued").strip() or "queued"
status_tag = re.sub(r"[^a-z0-9]+", "-", status_label.lower()).strip("-") or "queued"
exec_fn = getattr(_SEARCH_FILE_CMDLET, "exec", None) metadata: Dict[str, Any] = {
if callable(exec_fn): "magnet_id": magnet_id,
exec_fn( "provider": "alldebrid",
None, "provider_view": "files",
["-plugin", "alldebrid", f"ID={magnet_id}"], "magnet_spec": magnet_spec,
config, "source_url": magnet_spec,
) "status": status_label,
except Exception: }
pass for key in ("filename", "name", "hash", "size", "statusCode", "ready"):
debug(f"[alldebrid] Sent magnet {magnet_id} to AllDebrid for download") value = magnet_info.get(key)
if value is not None:
metadata[key] = value
return {
"table": "alldebrid",
"provider": "alldebrid",
"plugin": "alldebrid",
"path": f"{_ALD_MAGNET_PREFIX}{magnet_id}",
"title": title,
"detail": f"Queued in AllDebrid ({status_label})",
"media_kind": "folder",
"tag": ["folder", f"status:{status_tag}", "provider:alldebrid"],
"columns": [
("Title", title),
("Status", status_label),
("Provider", "alldebrid"),
("Magnet ID", magnet_id),
],
"full_metadata": metadata,
"source_url": magnet_spec,
"_selection_action": ["search-file", "-plugin", "alldebrid", f"ID={magnet_id}"],
}
def prepare_magnet( def prepare_magnet(
magnet_spec: str, magnet_spec: str,
config: Dict[str, Any], config: Dict[str, Any],
) -> tuple[Optional[AllDebridClient], Optional[int]]: ) -> tuple[Optional[AllDebridClient], Optional[int], Dict[str, Any]]:
api_key = _get_debrid_api_key(config or {}) api_key = _get_debrid_api_key(config or {})
if not api_key: if not api_key:
log("AllDebrid API key not configured. Use .config to set it.", file=sys.stderr) log("AllDebrid API key not configured. Use .config to set it.", file=sys.stderr)
return None, None return None, None, {}
try: try:
client = AllDebridClient(api_key) client = AllDebridClient(api_key)
except Exception as exc: except Exception as exc:
log(f"Failed to initialize AllDebrid client: {exc}", file=sys.stderr) log(f"Failed to initialize AllDebrid client: {exc}", file=sys.stderr)
return None, None return None, None, {}
try: try:
magnet_info = client.magnet_add(magnet_spec) magnet_info = client.magnet_add(magnet_spec)
@@ -427,13 +452,12 @@ def prepare_magnet(
magnet_id = int(magnet_id_val) magnet_id = int(magnet_id_val)
if magnet_id <= 0: if magnet_id <= 0:
log(f"AllDebrid magnet submission failed: {magnet_info}", file=sys.stderr) log(f"AllDebrid magnet submission failed: {magnet_info}", file=sys.stderr)
return None, None return None, None, {}
except Exception as exc: except Exception as exc:
log(f"Failed to submit magnet to AllDebrid: {exc}", file=sys.stderr) log(f"Failed to submit magnet to AllDebrid: {exc}", file=sys.stderr)
return None, None return None, None, {}
_dispatch_alldebrid_magnet_search(magnet_id, config) return client, magnet_id, magnet_info if isinstance(magnet_info, dict) else {}
return client, magnet_id
def _flatten_files_with_relpath(items: Any) -> Iterable[Dict[str, Any]]: def _flatten_files_with_relpath(items: Any) -> Iterable[Dict[str, Any]]:
@@ -457,7 +481,7 @@ def download_magnet(
path_from_result: Callable[[Any], Path], path_from_result: Callable[[Any], Path],
on_emit: Callable[[Path, str, str, Dict[str, Any]], None], on_emit: Callable[[Path, str, str, Dict[str, Any]], None],
) -> tuple[int, Optional[int]]: ) -> tuple[int, Optional[int]]:
client, magnet_id = prepare_magnet(magnet_spec, config) client, magnet_id, _magnet_info = prepare_magnet(magnet_spec, config)
if client is None or magnet_id is None: if client is None or magnet_id is None:
return 0, None return 0, None
@@ -789,8 +813,20 @@ class AllDebrid(TablePluginMixin, Provider):
cfg = self.config if isinstance(self.config, dict) else {} cfg = self.config if isinstance(self.config, dict) else {}
try: try:
prepare_magnet(spec, cfg) _client, magnet_id, magnet_info = prepare_magnet(spec, cfg)
return True, None if magnet_id is None:
return False, None
return True, {
"action": "emit_items",
"items": [
_build_queued_magnet_item(
magnet_spec=str(url),
magnet_id=int(magnet_id),
magnet_info=magnet_info,
)
],
"exit_code": 0,
}
except Exception: except Exception:
return False, None return False, None
@@ -804,14 +840,6 @@ class AllDebrid(TablePluginMixin, Provider):
dom = str(d or "").strip().lower() dom = str(d or "").strip().lower()
if dom and dom not in patterns: if dom and dom not in patterns:
patterns.append(dom) patterns.append(dom)
debug_panel(
"AllDebrid host cache",
[
("cached_domains", len(cached)),
("total_patterns", len(patterns)),
],
border_style="magenta",
)
except Exception: except Exception:
pass pass
return tuple(patterns) return tuple(patterns)
@@ -866,8 +894,6 @@ class AllDebrid(TablePluginMixin, Provider):
log(f"[alldebrid] Failed to init client: {exc}", file=sys.stderr) log(f"[alldebrid] Failed to init client: {exc}", file=sys.stderr)
return None return None
log(f"[alldebrid] download routing target={target}", file=sys.stderr)
# Prefer provider title as the output filename; later we may override if unlocked URL has a better basename. # Prefer provider title as the output filename; later we may override if unlocked URL has a better basename.
suggested = sanitize_filename(str(getattr(result, "title", "") or "").strip()) suggested = sanitize_filename(str(getattr(result, "title", "") or "").strip())
suggested_name = suggested if suggested else None suggested_name = suggested if suggested else None
@@ -914,8 +940,7 @@ class AllDebrid(TablePluginMixin, Provider):
continue continue
fh.write(chunk) fh.write(chunk)
return dest if dest.exists() else None return dest if dest.exists() else None
except Exception as exc2: except Exception:
log(f"[alldebrid] raw stream (unlocked) failed: {exc2}", file=sys.stderr)
return None return None
# Otherwise, use standard downloader with guardrails. # Otherwise, use standard downloader with guardrails.
@@ -961,9 +986,8 @@ class AllDebrid(TablePluginMixin, Provider):
unlocked = client.resolve_unlock_link(target, poll=True, max_wait_seconds=45, poll_interval_seconds=5) unlocked = client.resolve_unlock_link(target, poll=True, max_wait_seconds=45, poll_interval_seconds=5)
if isinstance(unlocked, str) and unlocked.strip().startswith(("http://", "https://")): if isinstance(unlocked, str) and unlocked.strip().startswith(("http://", "https://")):
unlocked_url = unlocked.strip() unlocked_url = unlocked.strip()
log(f"[alldebrid] unlock -> {unlocked_url}", file=sys.stderr) except Exception:
except Exception as exc: pass
log(f"[alldebrid] Failed to unlock link: {exc}", file=sys.stderr)
if unlocked_url != target: if unlocked_url != target:
# Prefer filename from unlocked URL path. # Prefer filename from unlocked URL path.
@@ -976,20 +1000,14 @@ class AllDebrid(TablePluginMixin, Provider):
# When using an unlocked URL different from the original hoster, stream it directly and do NOT fall back to the public URL. # When using an unlocked URL different from the original hoster, stream it directly and do NOT fall back to the public URL.
allow_html = unlocked_url != target allow_html = unlocked_url != target
log(
f"[alldebrid] downloading from {unlocked_url} (allow_html={allow_html})",
file=sys.stderr,
)
downloaded = _download_unlocked(unlocked_url, allow_html=allow_html) downloaded = _download_unlocked(unlocked_url, allow_html=allow_html)
if downloaded: if downloaded:
log(f"[alldebrid] downloaded -> {downloaded}", file=sys.stderr)
return downloaded return downloaded
# If unlock failed entirely and we never changed URL, allow a single attempt on the original target. # If unlock failed entirely and we never changed URL, allow a single attempt on the original target.
if unlocked_url == target: if unlocked_url == target:
downloaded = _download_unlocked(target, allow_html=False) downloaded = _download_unlocked(target, allow_html=False)
if downloaded: if downloaded:
log(f"[alldebrid] downloaded (original target) -> {downloaded}", file=sys.stderr)
return downloaded return downloaded
return None return None
@@ -1172,7 +1190,6 @@ class AllDebrid(TablePluginMixin, Provider):
if active_id is not None: if active_id is not None:
try: try:
magnet_id = int(active_id) magnet_id = int(active_id)
debug(f"[download_items] Found magnet_id {magnet_id}, downloading files directly")
cfg = config if isinstance(config, dict) else (self.config or {}) cfg = config if isinstance(config, dict) else (self.config or {})
count = self._download_magnet_by_id( count = self._download_magnet_by_id(
magnet_id, magnet_id,
@@ -1183,10 +1200,9 @@ class AllDebrid(TablePluginMixin, Provider):
quiet_mode, quiet_mode,
path_from_result, path_from_result,
) )
debug(f"[download_items] _download_magnet_by_id returned {count}")
return count return count
except Exception as e: except Exception:
debug(f"[download_items] Failed to download by magnet_id: {e}") pass
spec = self._resolve_magnet_spec_from_result(result) spec = self._resolve_magnet_spec_from_result(result)
if not spec: if not spec:
@@ -1329,11 +1345,8 @@ class AllDebrid(TablePluginMixin, Provider):
unlocked = client.unlock_link(locked_url) unlocked = client.unlock_link(locked_url)
if unlocked: if unlocked:
file_url = unlocked file_url = unlocked
debug(f"[alldebrid] Unlocked restricted link for {file_name}") except Exception:
else: pass
debug(f"[alldebrid] Failed to unlock {locked_url}, trying locked URL")
except Exception as exc:
debug(f"[alldebrid] unlock_link failed: {exc}, trying locked URL")
rel_path_obj = Path(relpath) rel_path_obj = Path(relpath)
target_path = adjust_output_dir_for_alldebrid( target_path = adjust_output_dir_for_alldebrid(
@@ -1354,8 +1367,7 @@ class AllDebrid(TablePluginMixin, Provider):
suggested_filename=suggested_name, suggested_filename=suggested_name,
pipeline_progress=progress, pipeline_progress=progress,
) )
except Exception as exc: except Exception:
debug(f"Failed to download {file_url}: {exc}")
continue continue
downloaded_path = path_from_result(result_obj) downloaded_path = path_from_result(result_obj)
+19 -42
View File
@@ -71,7 +71,7 @@
"(wayupload\\.com/[a-z0-9]{12}\\.html)" "(wayupload\\.com/[a-z0-9]{12}\\.html)"
], ],
"regexp": "(turbobit5?a?\\.(net|cc|com)/([a-z0-9]{12}))|(turbobif\\.(net|cc|com)/([a-z0-9]{12}))|(turb[o]?\\.(to|cc|pw)\\/([a-z0-9]{12}))|(turbobit\\.(net|cc)/download/free/([a-z0-9]{12}))|((trbbt|tourbobit|torbobit|tbit|turbobita|trbt)\\.(net|cc|com|to)/([a-z0-9]{12}))|((turbobit\\.cloud/turbo/[a-z0-9]+))|((wayupload\\.com/[a-z0-9]{12}\\.html))", "regexp": "(turbobit5?a?\\.(net|cc|com)/([a-z0-9]{12}))|(turbobif\\.(net|cc|com)/([a-z0-9]{12}))|(turb[o]?\\.(to|cc|pw)\\/([a-z0-9]{12}))|(turbobit\\.(net|cc)/download/free/([a-z0-9]{12}))|((trbbt|tourbobit|torbobit|tbit|turbobita|trbt)\\.(net|cc|com|to)/([a-z0-9]{12}))|((turbobit\\.cloud/turbo/[a-z0-9]+))|((wayupload\\.com/[a-z0-9]{12}\\.html))",
"status": false "status": true
}, },
"hitfile": { "hitfile": {
"name": "hitfile", "name": "hitfile",
@@ -92,7 +92,7 @@
"(hitfile\\.net/[a-z0-9A-Z]{4,9})" "(hitfile\\.net/[a-z0-9A-Z]{4,9})"
], ],
"regexp": "(hitf\\.(to|cc)/([a-z0-9A-Z]{4,9}))|(htfl\\.(net|to|cc)/([a-z0-9A-Z]{4,9}))|(hitfile\\.(net)/download/free/([a-z0-9A-Z]{4,9}))|((hitfile\\.net/[a-z0-9A-Z]{4,9}))", "regexp": "(hitf\\.(to|cc)/([a-z0-9A-Z]{4,9}))|(htfl\\.(net|to|cc)/([a-z0-9A-Z]{4,9}))|(hitfile\\.(net)/download/free/([a-z0-9A-Z]{4,9}))|((hitfile\\.net/[a-z0-9A-Z]{4,9}))",
"status": false "status": true
}, },
"mega": { "mega": {
"name": "mega", "name": "mega",
@@ -165,40 +165,6 @@
"alldebrid\\.com/f/([a-zA-Z0-9\\_\\-]+)" "alldebrid\\.com/f/([a-zA-Z0-9\\_\\-]+)"
] ]
}, },
"clicknupload": {
"name": "clicknupload",
"type": "premium",
"domains": [
"clicknupload.click",
"clickndownload.cc",
"clickndownload.click",
"clickndownload.link",
"clickndownload.name",
"clickndownload.org",
"clickndownload.space",
"clickndownload.xyz",
"clicknupload.cc",
"clicknupload.club",
"clicknupload.co",
"clicknupload.download",
"clicknupload.link",
"clicknupload.name",
"clicknupload.one",
"clicknupload.online",
"clicknupload.org",
"clicknupload.red",
"clicknupload.site",
"clicknupload.space",
"clicknupload.to",
"clicknupload.vip",
"clicknupload.xyz"
],
"regexps": [
"clicknupload\\.(link|org|red|co|cc|vip|to|club|click|xyz|online|download|site|space|one|name)/([a-zA-Z0-9]+)",
"clickndownload\\.(org|space|link|click|link|xyz|name|cc)/([a-zA-Z0-9]+)"
],
"regexp": "(clicknupload\\.(link|org|red|co|cc|vip|to|club|click|xyz|online|download|site|space|one|name)/([a-zA-Z0-9]+))|(clickndownload\\.(org|space|link|click|link|xyz|name|cc)/([a-zA-Z0-9]+))"
},
"clipwatching": { "clipwatching": {
"name": "clipwatching", "name": "clipwatching",
"type": "premium", "type": "premium",
@@ -213,7 +179,7 @@
}, },
"dailyuploads": { "dailyuploads": {
"name": "dailyuploads", "name": "dailyuploads",
"type": "free", "type": "premium",
"domains": [ "domains": [
"dailyuploads.net" "dailyuploads.net"
], ],
@@ -375,7 +341,7 @@
"(filespace\\.com/[a-zA-Z0-9]{12})" "(filespace\\.com/[a-zA-Z0-9]{12})"
], ],
"regexp": "(filespace\\.com/fd/([a-zA-Z0-9]{12}))|((filespace\\.com/[a-zA-Z0-9]{12}))", "regexp": "(filespace\\.com/fd/([a-zA-Z0-9]{12}))|((filespace\\.com/[a-zA-Z0-9]{12}))",
"status": false "status": true
}, },
"filezip": { "filezip": {
"name": "filezip", "name": "filezip",
@@ -463,7 +429,7 @@
"isra\\.cloud/\\?op=report_file&id=([0-9a-zA-Z]{12})" "isra\\.cloud/\\?op=report_file&id=([0-9a-zA-Z]{12})"
], ],
"regexp": "((isra\\.cloud/[0-9a-zA-Z]{12}))|(isra\\.cloud/\\?op=report_file&id=([0-9a-zA-Z]{12}))", "regexp": "((isra\\.cloud/[0-9a-zA-Z]{12}))|(isra\\.cloud/\\?op=report_file&id=([0-9a-zA-Z]{12}))",
"status": false, "status": true,
"hardRedirect": [ "hardRedirect": [
"isra\\.cloud/([0-9a-zA-Z]{12})" "isra\\.cloud/([0-9a-zA-Z]{12})"
] ]
@@ -482,7 +448,7 @@
"(katfile\\.com/[0-9a-zA-Z]{12})" "(katfile\\.com/[0-9a-zA-Z]{12})"
], ],
"regexp": "(katfile\\.(cloud|online|vip|ws|space)/([0-9a-zA-Z]{12}))|((katfile\\.com/[0-9a-zA-Z]{12}))", "regexp": "(katfile\\.(cloud|online|vip|ws|space)/([0-9a-zA-Z]{12}))|((katfile\\.com/[0-9a-zA-Z]{12}))",
"status": false "status": true
}, },
"mediafire": { "mediafire": {
"name": "mediafire", "name": "mediafire",
@@ -695,6 +661,17 @@
"uploadrar.com/([0-9a-zA-Z]{12})" "uploadrar.com/([0-9a-zA-Z]{12})"
] ]
}, },
"uploady": {
"name": "uploady",
"type": "premium",
"domains": [
"uploady.io"
],
"regexps": [
"(uploady\\.io/[0-9a-zA-Z]{12})"
],
"regexp": "(uploady\\.io/[0-9a-zA-Z]{12})"
},
"usersdrive": { "usersdrive": {
"name": "usersdrive", "name": "usersdrive",
"type": "free", "type": "free",
@@ -17929,9 +17906,9 @@
"generic.tld" "generic.tld"
], ],
"regexps": [ "regexps": [
"((example.com|1fichier.com|4shared.com|vev.io|clipwatching.com|clicknupload.click|playvidto.com|uploadrar.com|simfileshare.net|usersdrive.com|fastbit.cc|dropgalaxy.in|uploadboy.com|file.al|filespace.com|uploader.link|9xupload.asia|hexupload.net|filefactory.com|filerio.in|drive.google.com|gigapeta.com|isra.cloud|katfile.com|mediafire.com|mega.co.nz|alldebrid.com|prefiles.com|rapidgator.net|alfafile.net|scribd.com|turbobit.net|hitfile.net|sendit.cloud|ddl.to|exload.com|uploadhaven.com|vidoza.net|mixdrop.co|dropapk.to|indishare.me|world-files.com|uploadbox.io|worldbytez.com|mp4upload.com|upload42.com|uploading.vn|filedot.to|zofile.com|spicyfile.com|modsbase.com|sharemods.com|dl-file.com|dosya.co|loadstar.club|dailyuploads.net|file-upload.com|uploadbank.com|filezip.cc|hot4share.com|streamtape.com)/folders?/[^'\"<>;]+)" "((example.com|1fichier.com|4shared.com|vev.io|clipwatching.com|playvidto.com|uploadrar.com|simfileshare.net|usersdrive.com|fastbit.cc|dropgalaxy.in|uploadboy.com|file.al|filespace.com|uploader.link|9xupload.asia|hexupload.net|filefactory.com|filerio.in|drive.google.com|gigapeta.com|isra.cloud|katfile.com|mediafire.com|mega.co.nz|alldebrid.com|prefiles.com|rapidgator.net|alfafile.net|scribd.com|turbobit.net|hitfile.net|sendit.cloud|ddl.to|exload.com|uploadhaven.com|vidoza.net|mixdrop.co|dropapk.to|indishare.me|world-files.com|uploadbox.io|worldbytez.com|mp4upload.com|upload42.com|uploading.vn|filedot.to|zofile.com|spicyfile.com|modsbase.com|sharemods.com|dl-file.com|dosya.co|loadstar.club|dailyuploads.net|uploady.io|file-upload.com|uploadbank.com|filezip.cc|hot4share.com|streamtape.com)/folders?/[^'\"<>;]+)"
], ],
"regexp": "((example.com|1fichier.com|4shared.com|vev.io|clipwatching.com|clicknupload.click|playvidto.com|uploadrar.com|simfileshare.net|usersdrive.com|fastbit.cc|dropgalaxy.in|uploadboy.com|file.al|filespace.com|uploader.link|9xupload.asia|hexupload.net|filefactory.com|filerio.in|drive.google.com|gigapeta.com|isra.cloud|katfile.com|mediafire.com|mega.co.nz|alldebrid.com|prefiles.com|rapidgator.net|alfafile.net|scribd.com|turbobit.net|hitfile.net|sendit.cloud|ddl.to|exload.com|uploadhaven.com|vidoza.net|mixdrop.co|dropapk.to|indishare.me|world-files.com|uploadbox.io|worldbytez.com|mp4upload.com|upload42.com|uploading.vn|filedot.to|zofile.com|spicyfile.com|modsbase.com|sharemods.com|dl-file.com|dosya.co|loadstar.club|dailyuploads.net|file-upload.com|uploadbank.com|filezip.cc|hot4share.com|streamtape.com)/folders?/[^'\"<>;]+)" "regexp": "((example.com|1fichier.com|4shared.com|vev.io|clipwatching.com|playvidto.com|uploadrar.com|simfileshare.net|usersdrive.com|fastbit.cc|dropgalaxy.in|uploadboy.com|file.al|filespace.com|uploader.link|9xupload.asia|hexupload.net|filefactory.com|filerio.in|drive.google.com|gigapeta.com|isra.cloud|katfile.com|mediafire.com|mega.co.nz|alldebrid.com|prefiles.com|rapidgator.net|alfafile.net|scribd.com|turbobit.net|hitfile.net|sendit.cloud|ddl.to|exload.com|uploadhaven.com|vidoza.net|mixdrop.co|dropapk.to|indishare.me|world-files.com|uploadbox.io|worldbytez.com|mp4upload.com|upload42.com|uploading.vn|filedot.to|zofile.com|spicyfile.com|modsbase.com|sharemods.com|dl-file.com|dosya.co|loadstar.club|dailyuploads.net|uploady.io|file-upload.com|uploadbank.com|filezip.cc|hot4share.com|streamtape.com)/folders?/[^'\"<>;]+)"
}, },
"google": { "google": {
"name": "google", "name": "google",