mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2025-10-23 15:11:08 +00:00
Compare commits
3 Commits
1.4.4
...
73595f3b50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73595f3b50 | ||
|
|
1e82283133 | ||
|
|
ab13dde9d2 |
37
CHANGELOG.md
37
CHANGELOG.md
@@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.4.4] - 2025-09-02
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Enhanced DecryptLabs CDM Support**: Comprehensive remote CDM functionality
|
||||||
|
- Full support for Widevine, PlayReady, and ChromeCDM through DecryptLabsRemoteCDM
|
||||||
|
- Enhanced session management and caching support for remote WV/PR operations
|
||||||
|
- Support for cached keys and improved license handling
|
||||||
|
- New CDM configurations for Chrome and PlayReady devices with updated User-Agent and service certificate
|
||||||
|
- **Advanced Configuration Options**: New device and language preferences
|
||||||
|
- Added configuration options for device certificate status list
|
||||||
|
- Enhanced language preference settings
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **DRM Decryption Enhancements**: Streamlined decryption process
|
||||||
|
- Simplified decrypt method by removing unused parameter and streamlined logic
|
||||||
|
- Improved DecryptLabs CDM configurations with better device support
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Matroska Tag Compliance**: Enhanced media container compatibility
|
||||||
|
- Fixed Matroska tag compliance with official specification
|
||||||
|
- **Application Branding**: Cleaned up version display
|
||||||
|
- Removed old devine version reference from banner to avoid developer confusion
|
||||||
|
- Updated branding while maintaining original GNU license compliance
|
||||||
|
- **IP Information Handling**: Improved geolocation services
|
||||||
|
- Enhanced get_ip_info functionality with better failover handling
|
||||||
|
- Added support for 429 error handling and multiple API provider fallback
|
||||||
|
- Implemented cached IP info retrieval with fallback tester to avoid rate limiting
|
||||||
|
- **Dependencies**: Streamlined package requirements
|
||||||
|
- Removed unnecessary data extra requirement from langcodes
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Deprecated version references in application banner for clarity
|
||||||
|
|
||||||
## [1.4.3] - 2025-08-20
|
## [1.4.3] - 2025-08-20
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ class DecryptLabsRemoteCDM:
|
|||||||
self.device_name = device_name
|
self.device_name = device_name
|
||||||
self.service_name = service_name or ""
|
self.service_name = service_name or ""
|
||||||
self.vaults = vaults
|
self.vaults = vaults
|
||||||
|
self.uch = self.host != "https://keyxtractor.decryptlabs.com"
|
||||||
|
|
||||||
self._device_type_str = device_type
|
self._device_type_str = device_type
|
||||||
if device_type:
|
if device_type:
|
||||||
@@ -308,32 +309,9 @@ class DecryptLabsRemoteCDM:
|
|||||||
if key and key.count("0") != len(key):
|
if key and key.count("0") != len(key):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if self.service_name:
|
session_keys = session.get("keys", [])
|
||||||
try:
|
if session_keys and len(session_keys) > 0:
|
||||||
key_ids = []
|
return True
|
||||||
if hasattr(pssh, "key_ids"):
|
|
||||||
key_ids = [kid.hex for kid in pssh.key_ids]
|
|
||||||
elif hasattr(pssh, "kids"):
|
|
||||||
key_ids = [kid.hex for kid in pssh.kids]
|
|
||||||
|
|
||||||
if key_ids:
|
|
||||||
response = self._http_session.post(
|
|
||||||
f"{self.host}/get-cached-keys",
|
|
||||||
json={"service": self.service_name, "kid": key_ids},
|
|
||||||
timeout=30,
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
return (
|
|
||||||
data.get("message") == "success"
|
|
||||||
and "cached_keys" in data
|
|
||||||
and isinstance(data["cached_keys"], list)
|
|
||||||
and len(data["cached_keys"]) > 0
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -366,11 +344,7 @@ class DecryptLabsRemoteCDM:
|
|||||||
session["pssh"] = pssh_or_wrm
|
session["pssh"] = pssh_or_wrm
|
||||||
init_data = self._get_init_data_from_pssh(pssh_or_wrm)
|
init_data = self._get_init_data_from_pssh(pssh_or_wrm)
|
||||||
|
|
||||||
if self.has_cached_keys(session_id):
|
request_data = {"scheme": self.device_name, "init_data": init_data, "get_cached_keys_if_exists": True}
|
||||||
self._load_cached_keys(session_id)
|
|
||||||
return b""
|
|
||||||
|
|
||||||
request_data = {"scheme": self.device_name, "init_data": init_data}
|
|
||||||
|
|
||||||
if self.device_name in ["L1", "L2", "SL2", "SL3"] and self.service_name:
|
if self.device_name in ["L1", "L2", "SL2", "SL3"] and self.service_name:
|
||||||
request_data["service"] = self.service_name
|
request_data["service"] = self.service_name
|
||||||
@@ -514,29 +488,6 @@ class DecryptLabsRemoteCDM:
|
|||||||
if key and key.count("0") != len(key):
|
if key and key.count("0") != len(key):
|
||||||
keys.append({"kid": kid.hex, "key": key, "type": "CONTENT"})
|
keys.append({"kid": kid.hex, "key": key, "type": "CONTENT"})
|
||||||
|
|
||||||
if not keys and self.service_name:
|
|
||||||
try:
|
|
||||||
key_ids = []
|
|
||||||
if hasattr(pssh, "key_ids"):
|
|
||||||
key_ids = [kid.hex for kid in pssh.key_ids]
|
|
||||||
elif hasattr(pssh, "kids"):
|
|
||||||
key_ids = [kid.hex for kid in pssh.kids]
|
|
||||||
|
|
||||||
if key_ids:
|
|
||||||
response = self._http_session.post(
|
|
||||||
f"{self.host}/get-cached-keys",
|
|
||||||
json={"service": self.service_name, "kid": key_ids},
|
|
||||||
timeout=30,
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
if data.get("message") == "success" and "cached_keys" in data:
|
|
||||||
keys = self._parse_cached_keys(data["cached_keys"])
|
|
||||||
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
session["keys"] = keys
|
session["keys"] = keys
|
||||||
|
|
||||||
def _parse_cached_keys(self, cached_keys_data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
def _parse_cached_keys(self, cached_keys_data: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import tempfile
|
|||||||
from difflib import SequenceMatcher
|
from difflib import SequenceMatcher
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
from xml.sax.saxutils import escape
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from requests.adapters import HTTPAdapter, Retry
|
from requests.adapters import HTTPAdapter, Retry
|
||||||
from xml.sax.saxutils import escape
|
|
||||||
|
|
||||||
from unshackle.core import binaries
|
from unshackle.core import binaries
|
||||||
from unshackle.core.config import config
|
from unshackle.core.config import config
|
||||||
|
|||||||
Reference in New Issue
Block a user