### Install PyXtream Source: https://github.com/superolmo/pyxtream/blob/main/README.md Install the pyxtream library using pip3. ```shell pip3 install pyxtream ``` -------------------------------- ### Event Listener Setup Source: https://github.com/superolmo/pyxtream/blob/main/pyxtream/html/index.html Sets up various event listeners for user interactions, including keypress for search input, click for search button, click for last 7 days filter, and scroll for infinite loading. Also includes initial DOMContentLoaded setup. ```javascript /* Setup event handlers */ document.getElementById("searchString_INPUT").addEventListener('keypress', logKey); document.getElementById("searchString_BTN").addEventListener('click', fetchSearchResults); document.getElementById("last7days_BTN").addEventListener('click', get_last_7days_action); window.addEventListener('scroll', handleScroll); // Initial load when the page first loads document.addEventListener('DOMContentLoaded', (event) => { // Load selected country from localStorage on page load const savedCountry = localStorage.getItem('pyxt ``` -------------------------------- ### Optional Local Installation Source: https://github.com/superolmo/pyxtream/blob/main/PYPI.md Install the Pyxtream package locally from the built distribution files for testing purposes. ```shell python3 -m pip install dist/pyxtream-0.7 ``` -------------------------------- ### Start Pyxtream Flask Web Interface Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Starts the Flask web interface for Pyxtream if enabled and configured. This allows for a web-based interaction with the Pyxtream client. ```python if USE_FLASK and enable_flask: self.printx("Starting Web Interface") self.flaskapp = FlaskWrap( self.name, self, self.html_template_folder, debug=debug_flask, port=flask_port ) self.flaskapp.start() else: self.printx("Web interface not running") ``` -------------------------------- ### Install PyXtream with REST API Support Source: https://github.com/superolmo/pyxtream/blob/main/README.md Install pyxtream with the extra dependencies for the REST API service, which requires Flask. ```shell pip3 install pyxtream[REST_API] ``` -------------------------------- ### Run Flask Application Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Starts the Flask development server. Use_reloader is set to False to prevent unintended restarts. ```python self.app.run(debug=self.debug, use_reloader=False, host=self.host, port=self.port) ``` -------------------------------- ### liveEpgByStream Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Retrieves the short Electronic Program Guide (EPG) for a live stream, showing upcoming scheduled programs. ```APIDOC ## liveEpgByStream(stream_id) ### Description Gets the short EPG for a LIVE stream, listing the next few programs scheduled to play. ### Method GET (Implicit) ### Endpoint `/streams/{stream_id}/epg/short` (Constructed internally) ### Parameters #### Path Parameters - **stream_id** (str) - Required - The ID of the live stream. ### Response #### Success Response (200) - **data** (list) - A list of upcoming EPG events for the stream. #### Response Example ```json { "example": "response body" } ``` ``` -------------------------------- ### Initialize Xtream Class Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Initializes the Xtream class with provider details, authentication credentials, and various configuration options. It handles setting up connection headers, authentication, and optionally starting a Flask web interface. ```python self.connection_headers = headers else: self.connection_headers = {'User-Agent': "Mozilla/5.0"} self.authenticate() if self.state['authenticated']: # Show message about Reload Timer configuration if self.threshold_time_sec > 0: self.printx(f"Reload timer is ON and set to {self.threshold_time_sec} seconds") else: self.printx("Reload timer is OFF") # Start Flask Web Interface if enabled if USE_FLASK and enable_flask: self.printx("Starting Web Interface") self.flaskapp = FlaskWrap( self.name, self, self.html_template_folder, debug=debug_flask, port=flask_port ) self.flaskapp.start() else: self.printx("Web interface not running") ``` -------------------------------- ### Get Live Categories URL Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs the URL to fetch live categories. Requires a base URL. ```python def get_live_categories_URL(base: str) -> str: return f"{base}&action=get_live_categories" ``` -------------------------------- ### Initiate Movie Download Source: https://github.com/superolmo/pyxtream/blob/main/pyxtream/html/index.html Initiates the download of a movie by getting the movie ID from the event target and constructing the download URL. ```javascript async function download_movie_action(event) { const btn = event.currentTarget; const movie_id = btn.getAttribute("movie_id"); const originalHtml = btn.innerHTML; const downloadUrl = `${API_BASE_URL}/download/${movie_id}`; } ``` -------------------------------- ### allLiveEpgByStream Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Retrieves all Electronic Program Guide (EPG) listings for a live stream, regardless of the day. ```APIDOC ## allLiveEpgByStream(stream_id) ### Description Gets all EPG listings for a LIVE stream, including events for all days. ### Method GET (Implicit) ### Endpoint `/streams/{stream_id}/epg/all` (Constructed internally) ### Parameters #### Path Parameters - **stream_id** (str) - Required - The ID of the live stream. ### Response #### Success Response (200) - **data** (list) - A list of all EPG events for the stream. #### Response Example ```json { "example": "response body" } ``` ``` -------------------------------- ### liveEpgByStreamAndLimit Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Retrieves a specified number of upcoming Electronic Program Guide (EPG) events for a live stream. ```APIDOC ## liveEpgByStreamAndLimit(stream_id, limit) ### Description Gets a specified number of upcoming EPG events for a LIVE stream. ### Method GET (Implicit) ### Endpoint `/streams/{stream_id}/epg?limit={limit}` (Constructed internally) ### Parameters #### Path Parameters - **stream_id** (str) - Required - The ID of the live stream. #### Query Parameters - **limit** (int) - Required - The maximum number of EPG events to retrieve. ### Response #### Success Response (200) - **data** (list) - A list of upcoming EPG events for the stream, up to the specified limit. #### Response Example ```json { "example": "response body" } ``` ``` -------------------------------- ### Get Live Streams URL Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs the URL to fetch all live streams. Requires a base URL. ```python def get_live_streams_URL(base: str) -> str: return f"{base}&action=get_live_streams" ``` -------------------------------- ### Run Flask Application Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Starts the Flask development server for the Pyxtream API. It configures the server to run in debug mode with specified host and port. ```python def run(self): self.app.run(debug=self.debug, use_reloader=False, host=self.host, port=self.port) ``` -------------------------------- ### Get Series URL Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs the URL to fetch all series. Requires a base URL. ```python def get_series_URL(base: str) -> str: return f"{base}&action=get_series" ``` -------------------------------- ### Get All EPG URL with Authentication Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs a URL to fetch all EPG data, requiring base URL, username, and password for authentication. ```python def get_all_epg_URL(base: str, username: str, password: str) -> str: return f"{base}/xmltv.php?username={username}&password={password}" ``` -------------------------------- ### Get Live Categories URL Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs a URL to retrieve a list of live TV categories. Requires the base URL. ```python def get_live_categories_URL(base: str) -> str: return f"{base}&action=get_live_categories}" ``` -------------------------------- ### Lock and Sync Dependencies with Poetry Source: https://github.com/superolmo/pyxtream/blob/main/PYPI.md Use these commands to ensure consistent project dependencies. 'poetry lock' creates or updates the lock file, and 'poetry sync' installs dependencies based on the lock file. ```shell poetry lock poetry sync poetry debug resolve ``` -------------------------------- ### Get Live Streams URL Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs a URL to retrieve a list of all live streams. Requires the base URL. ```python def get_live_streams_URL(base: str) -> str: return f"{base}&action=get_live_streams}" ``` -------------------------------- ### Run Functional Test Source: https://github.com/superolmo/pyxtream/blob/main/README.md Execute the functional test script to authenticate, load, and search streams. If Flask is installed, a web interface will be available at http://localhost:5000. ```shell python3 functional_test.py ``` -------------------------------- ### Get All EPG Source: https://github.com/superolmo/pyxtream/blob/main/README.md Retrieves all available Electronic Program Guide (EPG) data across all streams. ```APIDOC ## xTream.allEpg ### Description Retrieves all available Electronic Program Guide (EPG) data across all streams. ### Method ```python allEpg() ``` ``` -------------------------------- ### Initial Search and Event Listener Setup Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream.html Initializes search if a search term is present in the URL, or sets up a focus listener to initialize search on user interaction. Also sets the initial value of the search box. ```javascript if (getSearchTerm()) { initialize(); searchBox.value = getSearchTerm(); onInput(); } else { searchBox.addEventListener("focus", initialize, {once: true}); } ``` -------------------------------- ### Get All Live EPG by Stream Source: https://github.com/superolmo/pyxtream/blob/main/README.md Retrieves all available Electronic Program Guide (EPG) data for a live stream. ```APIDOC ## xTream.allLiveEpgByStream ### Description Retrieves all available Electronic Program Guide (EPG) data for a live stream. ### Method ```python allLiveEpgByStream(stream_id: int) ``` ### Parameters - **stream_id** (int) - The ID of the live stream. ``` -------------------------------- ### Get Live EPG URL by Stream ID and Limit Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs a URL to fetch live EPG data for a specific stream with a limit on the number of entries. Requires base URL, stream ID, and limit. ```python def get_live_epg_URL_by_stream_and_limit(stream_id, limit, base: str) -> str: return f"{base}&action=get_short_epg&stream_id={stream_id}&limit={limit}" ``` -------------------------------- ### Get Live EPG by Stream Source: https://github.com/superolmo/pyxtream/blob/main/README.md Retrieves Electronic Program Guide (EPG) data for a live stream using its ID. ```APIDOC ## xTream.liveEpgByStream ### Description Retrieves Electronic Program Guide (EPG) data for a live stream using its ID. ### Method ```python liveEpgByStream(stream_id: int) ``` ### Parameters - **stream_id** (int) - The ID of the live stream. ``` -------------------------------- ### Initialize and Load IPTV Data Source: https://github.com/superolmo/pyxtream/blob/main/README.md Initialize the XTream object with server details and load IPTV content. Authentication status is checked before loading. ```python from pyxtream import XTream xt = XTream(servername, username, password, url) if xt.authData != {}: xt.load_iptv() else: print("Could not connect") ``` -------------------------------- ### Get All Live EPG URL by Stream ID Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs a URL to fetch all live EPG data for a specific stream. Requires the base URL and stream ID. ```python def get_all_live_epg_URL_by_stream(stream_id, base: str) -> str: return f"{base}&action=get_simple_data_table&stream_id={stream_id}" ``` -------------------------------- ### Get Live EPG by Stream ID Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Fetches the short Electronic Program Guide (EPG) data for a live stream, showing upcoming programs. ```python return self._get_request(api.get_live_epg_URL_by_stream(stream_id, self.base_url)) ``` -------------------------------- ### Get Live EPG by Stream and Limit Source: https://github.com/superolmo/pyxtream/blob/main/README.md Retrieves Electronic Program Guide (EPG) data for a live stream, limited to a specified number of entries. ```APIDOC ## xTream.liveEpgByStreamAndLimit ### Description Retrieves Electronic Program Guide (EPG) data for a live stream, limited to a specified number of entries. ### Method ```python liveEpgByStreamAndLimit(stream_id: int, limit: int) ``` ### Parameters - **stream_id** (int) - The ID of the live stream. - **limit** (int) - The maximum number of EPG entries to retrieve. ``` -------------------------------- ### Configure PyPI Token for Publishing Source: https://github.com/superolmo/pyxtream/blob/main/PYPI.md Set your PyPI API token for authentication. Replace '' with your actual token. ```shell poetry config pypi-token.pypi ``` -------------------------------- ### Get Thread Daemon Status Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves the daemon status of the thread. This must be set before start() is called. Daemon threads allow the entire Python program to exit when only daemon threads are left. ```python @property def daemon(self): """A boolean value indicating whether this thread is a daemon thread. This must be set before start() is called, otherwise RuntimeError is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and therefore all threads created in the main thread default to daemon = False. The entire Python program exits when only daemon threads are left. """ assert self._initialized, "Thread.__init__() not called" return self._daemonic ``` -------------------------------- ### Initialize Search Functionality in JavaScript Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Asynchronously loads the search index script and initializes the search functionality. Handles potential errors during script loading and updates the UI accordingly. Also sets up navigation click handling to clear search. ```javascript async function initialize() { try { search = await new Promise((resolve, reject) => { const script = document.createElement("script"); script.type = "text/javascript"; script.async = true; script.onload = () => resolve(window.pdocSearch); script.onerror = (e) => reject(e); script.src = "../search.js"; document.getElementsByTagName("head")\[0\]appendChild(script); }); } catch (e) { console.error("Cannot fetch pdoc search index"); searchErr = "Cannot fetch search index."; } onInput(); document.querySelector("nav.pdoc").addEventListener("click", e => { if (e.target.hash) { searchBox.value = ""; searchBox.dispatchEvent(new Event("input")); } }); } ``` -------------------------------- ### Initialize Search Functionality Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/version.html Asynchronously loads the search index script and initializes the search functionality. Handles potential errors during script loading. ```javascript async function initialize() { try { search = await new Promise((resolve, reject) => { const script = document.createElement("script"); script.type = "text/javascript"; script.async = true; script.onload = () => resolve(window.pdocSearch); script.onerror = (e) => reject(e); script.src = "../search.js"; document.getElementsByTagName("head")[0].appendChild(script); }); } catch (e) { console.error("Cannot fetch pdoc search index"); searchErr = "Cannot fetch search index."; } onInput(); document.querySelector("nav.pdoc").addEventListener("click", e => { if (e.target.hash) { searchBox.value = ""; searchBox.dispatchEvent(new Event("input")); } }); } ``` -------------------------------- ### Build Project Documentation with pdoc Source: https://github.com/superolmo/pyxtream/blob/main/PYPI.md This command removes the old docs directory and then generates new documentation for the 'pyxtream' package, saving it to the 'docs' folder. ```shell rm -rf docs poetry run pdoc -n -o docs pyxtream ``` -------------------------------- ### Internal Video Download Implementation Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Handles the actual downloading of a video stream from a given URL to a specified file path. It sets up necessary headers and attempts the download, returning true on success and false on failure. ```python ret_code = False mb_size = 1024*1024 headers = self.connection_headers.copy() try: # ... download logic ... ``` -------------------------------- ### Generic GET Request with Error Handling Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Performs a generic GET request with specified timeouts and error handling. It retries the request up to 10 times and returns JSON data or None if an error occurs. ```python def _get_request(self, url: str, timeout: Tuple[int, int] = (2, 15)) -> Optional[dict]: """Generic GET Request with Error handling Args: URL (str): The URL where to GET content timeout (Tuple[int, int], optional): Connection and Downloading Timeout. Defaults to (2,15). Returns: Optional[dict]: JSON dictionary of the loaded data, or None """ kb_size = 1024 all_data = [] down_stats = {"bytes": 0, "kbytes": 0, "mbytes": 0, "start": 0.0, "delta_sec": 0.0} response = None for attempt in range(10): try: response = requests.get( url, stream=True, timeout=timeout, headers=self.connection_headers ) response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx) break except requests.exceptions.RequestException as e: self._handle_request_exception(e) return None # If there is an answer from the remote server if response is not None and response.status_code in (200, 206): down_stats["start"] = time.perf_counter() # Set downloaded size down_stats["bytes"] = 0 # Set stream blocks block_bytes = int(1*kb_size*kb_size) # 1 MB # Grab data by block_bytes for data in response.iter_content(block_bytes, decode_unicode=False): ``` -------------------------------- ### Generic GET Request with Error Handling Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html This function performs a generic GET request with configurable timeouts and retries. It handles request exceptions by calling `_handle_request_exception` and returns the JSON response or None if an error occurs. ```python def _get_request(self, url: str, timeout: Tuple[int, int] = (2, 15)) -> Optional[dict]: """Generic GET Request with Error handling Args: URL (str): The URL where to GET content timeout (Tuple[int, int], optional): Connection and Downloading Timeout. Defaults to (2,15). Returns: Optional[dict]: JSON dictionary of the loaded data, or None """ kb_size = 1024 all_data = [] down_stats = {"bytes": 0, "kbytes": 0, "mbytes": 0, "start": 0.0, "delta_sec": 0.0} response = None for attempt in range(10): try: response = requests.get( url, stream=True, timeout=timeout, headers=self.connection_headers ) response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx) break except requests.exceptions.RequestException as e: self._handle_request_exception(e) return None # If there is an answer from the remote server if response is not None and response.status_code in (200, 206): down_stats["start"] = time.perf_counter() # Set downloaded size down_stats["bytes"] = 0 # Set stream blocks block_bytes = int(1*kb_size*kb_size) # 1 MB # Grab data by block_bytes for data in response.iter_content(block_bytes, decode_unicode=False): down_stats["bytes"] += len(data) down_stats["kbytes"] = down_stats["bytes"]/kb_size down_stats["mbytes"] = down_stats["bytes"]/kb_size/kb_size down_stats["delta_sec"] = time.perf_counter() - down_stats["start"] if down_stats["delta_sec"] > 0: download_speed_average = down_stats["kbytes"] // down_stats["delta_sec"] else: download_speed_average = 0 # Show progress msg = f'Downloading {down_stats["kbytes"]:.1f} kB at {download_speed_average:.0f} kB/s' sys.stdout.write("\r" + msg) sys.stdout.flush() all_data.append(data) sys.stdout.write(" - Done\n") sys.stdout.flush() full_content = b''.join(all_data) return json.loads(full_content) self.printx(f"HTTP error {response.status_code} while retrieving from {url}") return None ``` -------------------------------- ### Initiate Video Download Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html This function constructs the filename for a stream and initiates the download process. It calls the internal `_download_video_impl` function and retries up to 10 times if the download fails. It returns the filename upon success or an empty string on failure. ```python fn = f"{self._slugify(stream.name)}.{stream.raw['container_extension']}" filename = osp.join(self.cache_path, fn) # If the url was correctly built and file does not exists, start downloading if url == "": return "" for attempt in range(10): if self._download_video_impl(url, filename): return filename return "" ``` -------------------------------- ### Initialize Pyxtream Class Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Instantiates the XTream class with provider details and configuration options. Handles cache path validation and default settings. Authentication is performed upon initialization if credentials are valid. ```python self.server = provider_url self.username = provider_username self.password = provider_password self.name = provider_name self.cache_path = cache_path self.hide_adult_content = hide_adult_content self.threshold_time_sec = reload_time_sec self.validate_json = validate_json self.auth_data = {} self.authorization = {'username': '', 'password': ''} self.groups = [] self.channels = [] self.series = [] self.movies = [] self.movies_30days = [] self.movies_7days = [] self.connection_headers = {} self.state = {'authenticated': False, 'loaded': False} # Used by REST API to get download progress self.download_progress: dict = {'StreamId': 0, 'Total': 0, 'Progress': 0} # get the pyxtream local path self.app_fullpath = osp.dirname(osp.realpath(__file__)) # prepare location of local html template self.html_template_folder = osp.join(self.app_fullpath, "html") # if the cache_path is specified, test that it is a directory if self.cache_path != "": # If the cache_path is not a directory, clear it if not osp.isdir(self.cache_path): self.printx(" - Cache Path is not a directory, using default '~/.xtream-cache/'") self.cache_path = "" # If the cache_path is still empty, use default if self.cache_path == "": self.cache_path = osp.expanduser("~/.xtream-cache/") if not osp.isdir(self.cache_path): makedirs(self.cache_path, exist_ok=True) self.printx(f"pyxtream cache path located at {self.cache_path}") if headers is not None: self.connection_headers = headers else: self.connection_headers = {'User-Agent': "Mozilla/5.0"} self.authenticate() if self.state['authenticated']: # Show message about Reload Timer configuration if self.threshold_time_sec > 0: self.printx(f"Reload timer is ON and set to {self.threshold_time_sec} seconds") else: self.printx("Reload timer is OFF") # Start Flask Web Interface if enabled if USE_FLASK and enable_flask: self.printx("Starting Web Interface") self.flaskapp = FlaskWrap( ``` -------------------------------- ### Get Download Progress Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves the progress of an ongoing stream download. ```APIDOC ## GET /get_download_progress// ### Description Retrieves the current progress of a stream download. ### Method GET ### Endpoint /get_download_progress// ### Parameters #### Path Parameters - **stream_id** (string) - Required - The identifier of the stream whose download progress is requested. ``` -------------------------------- ### Get Series Info Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves information about a series based on its ID. ```APIDOC ## GET /get_series/ ### Description Retrieves detailed information about a specific series using its unique ID. ### Method GET ### Endpoint /get_series/ ### Parameters #### Path Parameters - **series_id** (integer) - Required - The ID of the series to retrieve information for. ### Response #### Success Response (200) - **series_info** (object) - An object containing details about the series. ``` -------------------------------- ### Initialize Episode Object Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Initializes an Episode object with XTream details, series information, group title, and episode data. It constructs the episode's URL and performs basic validation. ```python def __init__(self, xtream: object, series_info, group_title, episode_info) -> None: # Raw JSON Episode self.raw = episode_info self.title = episode_info["title"] self.name = self.title self.group_title = group_title self.id = episode_info["id"] self.container_extension = episode_info["container_extension"] self.episode_number = episode_info["episode_num"] self.av_info = episode_info["info"] self.logo = series_info.get("cover", "") self.logo_path = xtream._get_logo_local_path(self.logo) if len(self.logo) > 0 else "" self.url = f"{xtream.server}/series/" f"{xtream.authorization['username']}/" f"{xtream.authorization['password']}/{self.id}.{self.container_extension}" # Check that the constructed URL is valid if not xtream._validate_url(self.url): print(f"{self.name} - Bad URL? `{self.url}`") ``` -------------------------------- ### Loading IPTV Streams Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html This code snippet demonstrates the logic for loading IPTV streams, categorizing them into live TV, VOD, or series, and saving them to the appropriate lists. It also handles grouping and logging skipped streams. ```python if loading_stream_type == self.live_type: if new_channel.group_id == "9999": self.printx(f" - xEverythingElse Channel -> {new_channel.name} - {new_channel.stream_type}") self.channels.append(new_channel) elif loading_stream_type == self.vod_type: if new_channel.group_id == "9999": self.printx(f" - xEverythingElse Channel -> {new_channel.name} - {new_channel.stream_type}") self.movies.append(new_channel) if new_channel.age_days_from_added < 31: self.movies_30days.append(new_channel) if new_channel.age_days_from_added < 7: self.movies_7days.append(new_channel) else: self.series.append(new_series) # Add stream to the specific Group if the_group is not None: if loading_stream_type != self.series_type: the_group.channels.append(new_channel) else: the_group.series.append(new_series) else: self.printx(f" - Group not found `{stream_channel['name']}`") print("\n") # Print information of which streams have been skipped if self.hide_adult_content: self.printx(f" - Skipped {skipped_adult_content} adult {loading_stream_type} streams") if skipped_no_name_content > 0: self.printx(f" - Skipped {skipped_no_name_content} " f"unprintable {loading_stream_type} streams") else: self.printx(f" - Could not load {loading_stream_type} Streams") self.state["loaded"] = True return True ``` -------------------------------- ### Get Series Information Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves detailed information about a specific series by its ID. ```APIDOC ## GET /get_series/ ### Description Retrieves detailed information for a given series ID. ### Method GET ### Endpoint /get_series/ ### Parameters #### Path Parameters - **series_id** (string) - Required - The unique identifier of the series. ``` -------------------------------- ### XTream Initialization and IPTV Loading Source: https://github.com/superolmo/pyxtream/blob/main/README.md Initializes the XTream client with provider credentials and loads IPTV data. The loaded data is then accessible through various attributes of the XTream object. ```APIDOC ## XTream Initialization and IPTV Loading ### Description Initializes the XTream client with provider credentials and loads IPTV data. The loaded data is then accessible through various attributes of the XTream object. ### Method ```python XTream(servername, username, password, url) ``` ### Parameters - **servername** (str) - The server name for the IPTV provider. - **username** (str) - The username for authentication. - **password** (str) - The password for authentication. - **url** (str) - The URL of the IPTV provider. ### Usage ```python from pyxtream import XTream xt = XTream(servername, username, password, url) if xt.authData != {}: xt.load_iptv() else: print("Could not connect") ``` ### Data Access After successful loading, data is available in: - `xTream.groups` - `xTream.channels` - `xTream.movies` - `xTream.series` ``` -------------------------------- ### Get Last 30 Days Data Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves data from the last 30 days. ```APIDOC ## GET /get_last_30days ### Description Retrieves data collected over the last 30 days. ### Method GET ### Endpoint /get_last_30days ### Response #### Success Response (200) - **data** (list) - A list of data entries from the last 30 days. ``` -------------------------------- ### Get Last 7 Days Data Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves data from the last 7 days. ```APIDOC ## GET /get_last_7days ### Description Retrieves data collected over the last 7 days. ### Method GET ### Endpoint /get_last_7days ### Response #### Success Response (200) - **data** (list) - A list of data entries from the last 7 days. ``` -------------------------------- ### Search Index Initialization Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Asynchronously loads the search index script and initializes the search functionality. It handles potential errors during script loading. ```javascript let search, searchErr; async function initialize() { try { search = await new Promise((resolve, reject) => { const script = document.createElement("script"); script.type = "text/javascript"; script.async = true; script.onload = () => resolve(window.pdocSearch); script.onerror = (e) => reject(e); script.src = "../search.js"; document.getElementsByTagName("head")\[0\]appendChild(script); }); } catch (e) { console.error("Cannot fetch pdoc search index"); searchErr = "Cannot fetch search index."; } onInput(); document.querySelector("nav.pdoc").addEventListener("click", e => { if (e.target.hash) { searchBox.value = ""; searchBox.dispatchEvent(new Event("input")); } }); } ``` -------------------------------- ### Get All EPG for All Streams Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Fetches a comprehensive list of EPG data for all available live streams. ```python return self._get_request(api.get_all_epg_URL(self.base_url, self.username, self.password)) ``` -------------------------------- ### Episode Class Initialization Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Initializes an Episode object with details from an XTream source. It constructs the episode URL and performs basic validation. ```python class Episode: def __init__(self, xtream: object, episode_info): self.group_title = group_title self.id = episode_info["id"] self.container_extension = episode_info["container_extension"] self.episode_number = episode_info["episode_num"] self.av_info = episode_info["info"] self.logo = series_info.get("cover", "") self.logo_path = xtream._get_logo_local_path(self.logo) if len(self.logo) > 0 else "" self.url = f"{xtream.server}/series/" \ f"{xtream.authorization['username']}/" \ f"{xtream.authorization['password']}/{self.id}.{self.container_extension}" # Check that the constructed URL is valid if not xtream._validate_url(self.url): print(f"{self.name} - Bad URL? `{self.url}`") ``` -------------------------------- ### Get Last 30 Days Streams Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves a list of streams from the last 30 days. ```APIDOC ## GET /get_last_30days ### Description Fetches a list of streams that were added or became available in the last 30 days. ### Method GET ### Endpoint /get_last_30days ``` -------------------------------- ### Export Dependencies to requirements.txt Source: https://github.com/superolmo/pyxtream/blob/main/PYPI.md Generate a 'requirements.txt' file from your Poetry project's dependencies, excluding hashes for broader compatibility. ```shell poetry export --without-hashes > requirements.txt ``` -------------------------------- ### Get Last 7 Days Streams Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves a list of streams from the last 7 days. ```APIDOC ## GET /get_last_7days ### Description Fetches a list of streams that were added or became available in the last 7 days. ### Method GET ### Endpoint /get_last_7days ``` -------------------------------- ### Episode Class Initialization Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Initializes an Episode object using data from a streaming service. It extracts episode details, constructs a playback URL, and performs basic URL validation. ```python def __init__(self, xtream: object, series_info, group_title, episode_info) -> None: # Raw JSON Episode self.raw = episode_info self.title = episode_info["title"] self.name = self.title self.group_title = group_title self.id = episode_info["id"] self.container_extension = episode_info["container_extension"] self.episode_number = episode_info["episode_num"] self.av_info = episode_info["info"] self.logo = series_info.get("cover", "") self.logo_path = xtream._get_logo_local_path(self.logo) if len(self.logo) > 0 else "" self.url = f"{xtream.server}/series/" f"{xtream.authorization['username']}/" f"{xtream.authorization['password']}/{self.id}.{self.container_extension}" # Check that the constructed URL is valid if not xtream._validate_url(self.url): print(f"{self.name} - Bad URL? `{self.url}`") ``` -------------------------------- ### Get Series URL Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs a URL to retrieve a list of all series. Requires the base URL. ```python def get_series_URL(base: str) -> str: return f"{base}&action=get_series}" ``` -------------------------------- ### allEpg Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Fetches a comprehensive list of Electronic Program Guide (EPG) data for all available streams. ```APIDOC ## allEpg() ### Description Retrieves the full EPG list for all available streams. ### Method GET (Implicit) ### Endpoint `/epg/all` (Constructed internally) ### Parameters None ### Response #### Success Response (200) - **data** (list) - A list containing EPG data for all streams. #### Response Example ```json { "example": "response body" } ``` ``` -------------------------------- ### Search Initialization Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream.html Asynchronously loads the search index script and initializes the search functionality. Handles potential errors during script loading and triggers an initial input event. ```javascript let search, searchErr; async function initialize() { try { search = await new Promise((resolve, reject) => { const script = document.createElement("script"); script.type = "text/javascript"; script.async = true; script.onload = () => resolve(window.pdocSearch); script.onerror = (e) => reject(e); script.src = "search.js"; document.getElementsByTagName("head")\[0\]appendChild(script); }); } catch (e) { console.error("Cannot fetch pdoc search index"); searchErr = "Cannot fetch search index."; } onInput(); document.querySelector("nav.pdoc").addEventListener("click", e => { if (e.target.hash) { searchBox.value = ""; searchBox.dispatchEvent(new Event("input")); } }); } ``` -------------------------------- ### Get VOD Info by ID Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Fetches Video On Demand (VOD) information for a specific VOD ID. ```python def vodInfoByID(self, vod_id): return self._get_request(api.get_VOD_info_URL_by_ID(vod_id, self.base_url), self.base_url) ``` -------------------------------- ### Get VOD Info by ID Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Retrieves information for a Video On Demand (VOD) item using its ID. ```python return self._get_request(api.get_VOD_info_URL_by_ID(vod_id, self.base_url), self.base_url) ``` -------------------------------- ### Load or Download Streams Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Attempts to load stream data from a local file. If the file is empty or does not exist, it downloads the data from the provider and saves it locally. Includes logic to skip adult content and streams without names. ```python # Get Streams # Try loading local file dt = 0 start = timer() all_streams = self._load_from_file(f"all_stream_{loading_stream_type}.json") # If file empty or does not exists, download it from remote if all_streams is None: # Load all Streams and save file locally all_streams = self._load_streams_from_provider(loading_stream_type) self._save_to_file(all_streams, f"all_stream_{loading_stream_type}.json") dt = timer() - start # If we got the STREAMS data, show the statistics and load Streams if all_streams is not None: self.printx(f"Loaded {len(all_streams)} {loading_stream_type} Streams in {dt:.3f} seconds") # Add Streams to dictionaries skipped_adult_content = 0 skipped_no_name_content = 0 self.printx(f"Processing {loading_stream_type} Streams...") start = timer() for stream_channel in all_streams: skip_stream = False # Validate JSON scheme if self.validate_json: if loading_stream_type == self.series_type: if not schemaValidator(stream_channel, SchemaType.SERIES_INFO): self.printx(stream_channel) ``` -------------------------------- ### Get Download Progress Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Retrieves the progress of an ongoing video stream download. Requires the stream ID. ```APIDOC ## GET /get_download_progress// ### Description Retrieves the progress of an ongoing video stream download. Requires the stream ID. ### Method GET ### Endpoint /get_download_progress// ### Parameters #### Path Parameters - **stream_id** (integer) - Required - The ID of the stream whose download progress is requested. ### Response #### Success Response (200) - **progress** (integer) - The current download progress percentage. ``` -------------------------------- ### Home Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Returns the HTML home page for the API. ```APIDOC ## GET / ### Description Returns the HTML home page for the API. ### Method GET ### Endpoint / ### Response #### Success Response (200) - **Content-Type**: text/html; charset=utf-8 ``` -------------------------------- ### Get Series Categories URL Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs the URL to fetch series categories. Requires a base URL. ```python def get_series_cat_URL(base: str) -> str: return f"{base}&action=get_series_categories" ``` -------------------------------- ### Series Class Initialization Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Initializes a Series object with information from an IPTV provider. It processes raw series data, extracts key attributes like name, logo, and series ID, and constructs a URL for accessing series details. ```python class Series: # Required by Hypnotix name = "" logo = "" series_id = "" plot = "" youtube_trailer = "" genre = "" # This contains the raw JSON data raw: dict = {} def __init__(self, xtream: object, series_info): series_info["added"] = series_info["last_modified"] # Raw JSON Series self.raw = series_info self.xtream = xtream # Required by Hypnotix self.name = series_info["name"] self.logo = series_info["cover"] self.logo_path = xtream._get_logo_local_path(self.logo) self.seasons = {} self.episodes = {} # Check if category_id key is available if "series_id" in series_info.keys(): self.series_id = int(series_info["series_id"]) # Check if plot key is available if "plot" in series_info.keys(): self.plot = series_info["plot"] # Check if youtube_trailer key is available if "youtube_trailer" in series_info.keys(): self.youtube_trailer = series_info["youtube_trailer"] # Check if genre key is available if "genre" in series_info.keys(): self.genre = series_info["genre"] self.url = f"{xtream.server}/series/" self.url += f"{xtream.authorization['username']}/" self.url += f"{xtream.authorization['password']}/{self.series_id}/" ``` -------------------------------- ### XTream Class Initialization Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Initializes the XTream class, which serves as the main interface for interacting with an IPTV provider. It configures connection details, authentication, and various settings like content filtering and caching. ```python class XTream: name = "" server = "" secure_server = "" username = "" password = "" base_url = "" base_url_ssl = "" cache_path = "" account_expiration: timedelta live_type = "Live" vod_type = "VOD" series_type = "Series" hide_adult_content = False live_catch_all_group = Group( {"category_id": "9999", "category_name": "xEverythingElse", "parent_id": 0}, live_type ) vod_catch_all_group = Group( {"category_id": "9999", "category_name": "xEverythingElse", "parent_id": 0}, vod_type ) series_catch_all_group = Group( {"category_id": "9999", "category_name": "xEverythingElse", "parent_id": 0}, series_type ) # If the cached JSON file is older than threshold_time_sec then load a new # JSON dictionary from the provider threshold_time_sec = -1 validate_json: bool = True def __init__( self, provider_name: str, provider_username: str, provider_password: str, provider_url: str, headers: dict = None, hide_adult_content: bool = False, cache_path: str = "", reload_time_sec: int = 60*60*8, validate_json: bool = False, enable_flask: bool = False, debug_flask: bool = True, flask_port: int = 5000 ): """Initialize Xtream Class Args: provider_name (str): Name of the IPTV provider provider_username (str): User name of the IPTV provider provider_password (str): Password of the IPTV provider provider_url (str): URL of the IPTV provider headers (dict, optional): HTTP headers to use for requests. Defaults to None. hide_adult_content (bool, optional): Whether to hide adult content. Defaults to False. cache_path (str, optional): Path to store cached data. Defaults to "". reload_time_sec (int, optional): Time in seconds after which to reload data. Defaults to 8 hours. validate_json (bool, optional): Whether to validate JSON responses. Defaults to False. enable_flask (bool, optional): Whether to enable the Flask API. Defaults to False. debug_flask (bool, optional): Whether to enable Flask debug mode. Defaults to True. flask_port (int, optional): Port for the Flask API. Defaults to 5000. """ ``` -------------------------------- ### Initialize Season Object Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Initializes a Season object with a given name. It also prepares an empty dictionary for episodes. ```python def __init__(self, name): self.name = name self.episodes = {} ``` -------------------------------- ### get_live_epg_URL_by_stream Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Generates the URL to retrieve EPG (Electronic Program Guide) data for a specific live stream. ```APIDOC ## get_live_epg_URL_by_stream ### Description Generates the URL to retrieve EPG (Electronic Program Guide) data for a specific live stream. ### Method GET ### Endpoint /api/v1/epg/live/{stream} ### Parameters #### Path Parameters - **stream** (string) - Required - The identifier of the live stream for which to retrieve EPG data. ``` -------------------------------- ### Page Load and Search Initialization Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/pyxtream.html Initializes the search functionality by dynamically loading the `search.js` script. It handles potential errors during script loading and calls `onInput` to display initial search results if a search term is present in the URL. The search box focus also triggers initialization. ```javascript let search, searchErr; async function initialize() { try { search = await new Promise((resolve, reject) => { const script = document.createElement("script"); script.type = "text/javascript"; script.async = true; script.onload = () => resolve(window.pdocSearch); script.onerror = (e) => reject(e); script.src = "../search.js"; document.getElementsByTagName("head")\[0\]appendChild(script); }); } catch (e) { console.error("Cannot fetch pdoc search index"); searchErr = "Cannot fetch search index."; } onInput(); document.querySelector("nav.pdoc").addEventListener("click", e => { if (e.target.hash) { searchBox.value = ""; searchBox.dispatchEvent(new Event("input")); } }); } if (getSearchTerm()) { initialize(); searchBox.value = getSearchTerm(); onInput(); } else { searchBox.addEventListener("focus", initialize, {once: true}); } ``` -------------------------------- ### FlaskWrap App Reference Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/rest_api.html Reference to the Flask application instance. ```python app ``` -------------------------------- ### Get Series Categories URL Source: https://github.com/superolmo/pyxtream/blob/main/docs/pyxtream/api.html Constructs a URL to retrieve a list of series categories. Requires the base URL. ```python def get_series_cat_URL(base: str) -> str: return f"{base}&action=get_series_categories}" ```