High-level architecture
The plugin operates in a request-response model:- User interaction - User selects providers and channels through Kodi’s UI
- Provider fetch - Plugin retrieves encrypted provider data from Firebase Remote Config
- Decryption - Encrypted data is decrypted using AES encryption keys
- Channel parsing - M3U playlists are parsed into channel objects
- Playback - Resolved stream URLs are played with appropriate headers and DRM configuration
Entry Point
main.py handles routing and UI operationsBackground Service
service.py prefetches providers on startupCore Library
lib/ contains all business logic modulesCaching Layer
StorageServer provides persistent caching
Plugin structure
Main entry point (main.py)
Themain.py file serves as the routing controller for the addon. It handles three primary modes:
- Default mode - Lists all available providers from main.py:19-42
- list_channels - Fetches and displays channels for a selected provider from main.py:45-87
- play - Resolves and plays a selected channel from main.py:90-151
mode parameter.
Background service (service.py)
The background service performs initialization tasks:- Clears all cached data on startup from service.py:7
- Prefetches provider list to warm up the cache from service.py:11
Library modules (lib/)
All core functionality is organized in thelib/ directory:
- config.py - Addon path resolution and cache initialization
- providers.py - Provider and channel management with caching
- m3u_parser.py - M3U playlist parsing logic
- crypto_utils.py - AES encryption/decryption utilities
- remote_config.py - Firebase Remote Config integration
- req.py - HTTP request wrapper with custom headers
- logger.py - Logging utilities for Kodi
Data flow
Provider retrieval flow
Channel playback flow
Routing system
The routing system inmain.py uses URL query parameters to navigate between views:
build_url() helper from main.py:15-16, which encodes parameters into query strings.
Caching strategy
The plugin implements a two-tier caching strategy using Kodi’s StorageServer:Provider cache
- Key:
"cricfy_providers"from providers.py:11 - TTL: 24 hours (configured in cache initialization)
- Data: JSON array of provider objects
- Invalidation: Manual via service.py or cache expiration
Channel cache
- Key:
"channels_{hash}"where hash is SHA256 of provider URL from providers.py:66 - TTL: 3600 seconds (1 hour) from providers.py:12
- Data: JSON object with channel list and fetch timestamp
- Invalidation: Time-based check from providers.py:72
Firebase Remote Config integration
The plugin uses Firebase Remote Config to dynamically retrieve API endpoints from remote_config.py:94-111. This allows changing backend URLs without updating the addon.Configuration flow
- Generate random UUID as app instance ID from remote_config.py:28-29
- Build request payload with app metadata from remote_config.py:47-60
- Send POST request to Firebase Remote Config API from remote_config.py:72-77
- Extract
cric_api2or fall back tocric_api1from remote_config.py:111 - Use API URL to fetch provider data from providers.py:33-40
Retry mechanism
The plugin attempts to fetch remote config up to 3 times before giving up from remote_config.py:99-106, ensuring resilience against temporary network failures.Encryption and decryption
All provider data and some playlist content is encrypted using AES-256-CBC encryption.Key management
Encryption keys are stored in secret files:resources/secret1.txt- Primary AES key and IV (hex format:key:iv) from crypto_utils.py:9-12resources/secret2.txt- Fallback AES key and IV
- key: AES encryption key (bytes)
- iv: Initialization vector (bytes)
Decryption process
Provider data decryption
From crypto_utils.py:42-63:- Clean Base64 input (remove whitespace)
- Decode Base64 to ciphertext bytes
- Try decryption with each available key
- Remove PKCS5/7 padding
- Validate result (must start with
{,[, or containhttp)
M3U content decryption
From crypto_utils.py:88-128:- Check if already plain M3U (starts with
#EXTM3U,#EXTINF, or#KODIPROP) - Extract encrypted parts using string slicing:
- Part 1: bytes 0-10
- Part 2: bytes 34 to -54
- Part 3: last 10 bytes
- Extract IV (bytes 10-34) and key (bytes -54 to -10)
- Decode all parts from Base64
- Decrypt using extracted key and IV
- Unpad and return UTF-8 string
The decryption logic implements multiple fallback mechanisms to handle different encryption schemes and ensure maximum compatibility.
