mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2025-10-23 15:11:08 +00:00
Compare commits
3 Commits
ed744205ad
...
1e82283133
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e82283133 | ||
|
|
ab13dde9d2 | ||
|
|
9fd0895128 |
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
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "unshackle"
|
name = "unshackle"
|
||||||
version = "1.4.3"
|
version = "1.4.4"
|
||||||
description = "Modular Movie, TV, and Music Archival Software."
|
description = "Modular Movie, TV, and Music Archival Software."
|
||||||
authors = [{ name = "unshackle team" }]
|
authors = [{ name = "unshackle team" }]
|
||||||
requires-python = ">=3.10,<3.13"
|
requires-python = ">=3.10,<3.13"
|
||||||
|
|||||||
@@ -345,7 +345,10 @@ class dl:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if self.cdm:
|
if self.cdm:
|
||||||
if hasattr(self.cdm, "device_type") and self.cdm.device_type.name in ["ANDROID", "CHROME"]:
|
if isinstance(self.cdm, DecryptLabsRemoteCDM):
|
||||||
|
drm_type = "PlayReady" if self.cdm.is_playready else "Widevine"
|
||||||
|
self.log.info(f"Loaded {drm_type} Remote CDM: DecryptLabs (L{self.cdm.security_level})")
|
||||||
|
elif hasattr(self.cdm, "device_type") and self.cdm.device_type.name in ["ANDROID", "CHROME"]:
|
||||||
self.log.info(f"Loaded Widevine CDM: {self.cdm.system_id} (L{self.cdm.security_level})")
|
self.log.info(f"Loaded Widevine CDM: {self.cdm.system_id} (L{self.cdm.security_level})")
|
||||||
else:
|
else:
|
||||||
self.log.info(
|
self.log.info(
|
||||||
@@ -874,7 +877,12 @@ class dl:
|
|||||||
),
|
),
|
||||||
licence=partial(
|
licence=partial(
|
||||||
service.get_playready_license
|
service.get_playready_license
|
||||||
if isinstance(self.cdm, PlayReadyCdm)
|
if (
|
||||||
|
isinstance(self.cdm, PlayReadyCdm)
|
||||||
|
or (
|
||||||
|
isinstance(self.cdm, DecryptLabsRemoteCDM) and self.cdm.is_playready
|
||||||
|
)
|
||||||
|
)
|
||||||
and hasattr(service, "get_playready_license")
|
and hasattr(service, "get_playready_license")
|
||||||
else service.get_widevine_license,
|
else service.get_widevine_license,
|
||||||
title=title,
|
title=title,
|
||||||
@@ -1201,10 +1209,22 @@ class dl:
|
|||||||
if not drm:
|
if not drm:
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(drm, Widevine) and not isinstance(self.cdm, WidevineCdm):
|
if isinstance(drm, Widevine):
|
||||||
self.cdm = self.get_cdm(self.service, self.profile, drm="widevine")
|
if not isinstance(self.cdm, (WidevineCdm, DecryptLabsRemoteCDM)) or (
|
||||||
elif isinstance(drm, PlayReady) and not isinstance(self.cdm, PlayReadyCdm):
|
isinstance(self.cdm, DecryptLabsRemoteCDM) and self.cdm.is_playready
|
||||||
self.cdm = self.get_cdm(self.service, self.profile, drm="playready")
|
):
|
||||||
|
widevine_cdm = self.get_cdm(self.service, self.profile, drm="widevine")
|
||||||
|
if widevine_cdm:
|
||||||
|
self.log.info("Switching to Widevine CDM for Widevine content")
|
||||||
|
self.cdm = widevine_cdm
|
||||||
|
elif isinstance(drm, PlayReady):
|
||||||
|
if not isinstance(self.cdm, (PlayReadyCdm, DecryptLabsRemoteCDM)) or (
|
||||||
|
isinstance(self.cdm, DecryptLabsRemoteCDM) and not self.cdm.is_playready
|
||||||
|
):
|
||||||
|
playready_cdm = self.get_cdm(self.service, self.profile, drm="playready")
|
||||||
|
if playready_cdm:
|
||||||
|
self.log.info("Switching to PlayReady CDM for PlayReady content")
|
||||||
|
self.cdm = playready_cdm
|
||||||
|
|
||||||
if isinstance(drm, Widevine):
|
if isinstance(drm, Widevine):
|
||||||
with self.DRM_TABLE_LOCK:
|
with self.DRM_TABLE_LOCK:
|
||||||
@@ -1477,25 +1497,16 @@ class dl:
|
|||||||
|
|
||||||
cdm_api = next(iter(x for x in config.remote_cdm if x["name"] == cdm_name), None)
|
cdm_api = next(iter(x for x in config.remote_cdm if x["name"] == cdm_name), None)
|
||||||
if cdm_api:
|
if cdm_api:
|
||||||
is_decrypt_lab = True if cdm_api["type"] == "decrypt_labs" else False
|
is_decrypt_lab = True if cdm_api.get("type") == "decrypt_labs" else False
|
||||||
if is_decrypt_lab:
|
if is_decrypt_lab:
|
||||||
device_type = cdm_api.get("device_type")
|
|
||||||
del cdm_api["name"]
|
del cdm_api["name"]
|
||||||
del cdm_api["type"]
|
del cdm_api["type"]
|
||||||
|
|
||||||
# Use the appropriate DecryptLabs CDM class based on device type
|
# All DecryptLabs CDMs use DecryptLabsRemoteCDM
|
||||||
if device_type == "PLAYREADY" or cdm_api.get("device_name") in ["SL2", "SL3"]:
|
|
||||||
from unshackle.core.cdm.decrypt_labs_remote_cdm import DecryptLabsRemotePlayReadyCDM
|
|
||||||
|
|
||||||
# Remove unused parameters for PlayReady CDM
|
|
||||||
cdm_params = cdm_api.copy()
|
|
||||||
cdm_params.pop("device_type", None)
|
|
||||||
cdm_params.pop("system_id", None)
|
|
||||||
return DecryptLabsRemotePlayReadyCDM(service_name=service, vaults=self.vaults, **cdm_params)
|
|
||||||
else:
|
|
||||||
return DecryptLabsRemoteCDM(service_name=service, vaults=self.vaults, **cdm_api)
|
return DecryptLabsRemoteCDM(service_name=service, vaults=self.vaults, **cdm_api)
|
||||||
else:
|
else:
|
||||||
del cdm_api["name"]
|
del cdm_api["name"]
|
||||||
|
if "type" in cdm_api:
|
||||||
del cdm_api["type"]
|
del cdm_api["type"]
|
||||||
return RemoteCdm(**cdm_api)
|
return RemoteCdm(**cdm_api)
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "1.4.3"
|
__version__ = "1.4.4"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -420,6 +420,15 @@ class Track:
|
|||||||
for drm in self.drm:
|
for drm in self.drm:
|
||||||
if isinstance(drm, PlayReady):
|
if isinstance(drm, PlayReady):
|
||||||
return drm
|
return drm
|
||||||
|
elif hasattr(cdm, 'is_playready'):
|
||||||
|
if cdm.is_playready:
|
||||||
|
for drm in self.drm:
|
||||||
|
if isinstance(drm, PlayReady):
|
||||||
|
return drm
|
||||||
|
else:
|
||||||
|
for drm in self.drm:
|
||||||
|
if isinstance(drm, Widevine):
|
||||||
|
return drm
|
||||||
|
|
||||||
return self.drm[0]
|
return self.drm[0]
|
||||||
|
|
||||||
|
|||||||
@@ -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