mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-09-19 07:32:37 +02:00
134 lines
4.4 KiB
Python
134 lines
4.4 KiB
Python
"""
|
|
Subscription models for provider packages and user entitlements.
|
|
"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
from typing import Dict, List, Optional, Set
|
|
|
|
|
|
@dataclass
|
|
class SubscriptionPackage:
|
|
"""Represents a subscription package with provider-specific naming"""
|
|
|
|
package_id: str
|
|
"""Internal ID (e.g., 'sports_package_2024', 'joyn_plus')"""
|
|
|
|
name: str
|
|
"""Display name (e.g., 'Sports Package', 'Sky Sport', 'Joyn Plus')"""
|
|
|
|
description: Optional[str] = None
|
|
"""Optional description of the package"""
|
|
|
|
price_info: Optional[str] = None
|
|
"""Optional price information (e.g., '€9.99/month', 'included')"""
|
|
|
|
channel_ids: List[str] = field(default_factory=list)
|
|
"""List of channel IDs included in this package"""
|
|
|
|
metadata: Dict[str, any] = field(default_factory=dict)
|
|
"""Provider-specific metadata (e.g., {'sky_id': 'SPORT1', 'category': 'sports'})"""
|
|
|
|
@property
|
|
def channel_count(self) -> int:
|
|
"""Number of channels in this package"""
|
|
return len(self.channel_ids)
|
|
|
|
|
|
@dataclass
|
|
class UserSubscription:
|
|
"""User's subscription status for a provider"""
|
|
|
|
provider: str
|
|
"""Provider name (e.g., 'joyn', 'magenta')"""
|
|
|
|
country: str
|
|
"""Country code (e.g., 'DE', 'AT')"""
|
|
|
|
active: bool = False
|
|
"""Whether the subscription is currently active"""
|
|
|
|
packages: List[SubscriptionPackage] = field(default_factory=list)
|
|
"""All subscription packages the user has access to"""
|
|
|
|
accessible_channel_ids: Set[str] = field(default_factory=set)
|
|
"""Set of all channel IDs the user can access (derived from packages)"""
|
|
|
|
valid_from: Optional[datetime] = None
|
|
"""When the subscription becomes/starts valid"""
|
|
|
|
valid_until: Optional[datetime] = None
|
|
"""When the subscription expires"""
|
|
|
|
status_message: Optional[str] = None
|
|
"""Human-readable status message (e.g., 'Active until 2024-12-31')"""
|
|
|
|
billing_status: Optional[str] = None
|
|
"""Billing status (e.g., 'paid', 'trial', 'expired', 'cancelled')"""
|
|
|
|
def __post_init__(self):
|
|
"""Populate derived fields after initialization"""
|
|
self._update_derived_fields()
|
|
|
|
def _update_derived_fields(self):
|
|
"""Update derived fields like accessible_channel_ids"""
|
|
self.accessible_channel_ids.clear()
|
|
for package in self.packages:
|
|
self.accessible_channel_ids.update(package.channel_ids)
|
|
|
|
@property
|
|
def has_packages(self) -> bool:
|
|
"""Check if user has any packages"""
|
|
return len(self.packages) > 0
|
|
|
|
@property
|
|
def package_count(self) -> int:
|
|
"""Number of packages"""
|
|
return len(self.packages)
|
|
|
|
@property
|
|
def accessible_channel_count(self) -> int:
|
|
"""Number of accessible channels"""
|
|
return len(self.accessible_channel_ids)
|
|
|
|
@property
|
|
def package_names(self) -> List[str]:
|
|
"""List of package names for display"""
|
|
return [pkg.name for pkg in self.packages]
|
|
|
|
def to_dict(self) -> Dict:
|
|
"""Convert to dictionary for JSON serialization"""
|
|
return {
|
|
"provider": self.provider,
|
|
"country": self.country,
|
|
"active": self.active,
|
|
"has_packages": self.has_packages,
|
|
"package_count": self.package_count,
|
|
"package_names": self.package_names,
|
|
"accessible_channel_count": self.accessible_channel_count,
|
|
"valid_from": self.valid_from.isoformat() if self.valid_from else None,
|
|
"valid_until": self.valid_until.isoformat() if self.valid_until else None,
|
|
"status_message": self.status_message,
|
|
"billing_status": self.billing_status,
|
|
"packages": [
|
|
{
|
|
"package_id": pkg.package_id,
|
|
"name": pkg.name,
|
|
"description": pkg.description,
|
|
"price_info": pkg.price_info,
|
|
"channel_count": pkg.channel_count,
|
|
"metadata": pkg.metadata,
|
|
}
|
|
for pkg in self.packages
|
|
],
|
|
}
|
|
|
|
def add_package(self, package: SubscriptionPackage):
|
|
"""Add a package and update derived fields"""
|
|
self.packages.append(package)
|
|
self._update_derived_fields()
|
|
|
|
def can_access_channel(self, channel_id: str) -> bool:
|
|
"""Check if user can access a specific channel"""
|
|
return channel_id in self.accessible_channel_ids
|