Home Documentation Integration Guides

Integration Guides

Complete guides for creating service scripts, setting up Telegram notifications, and configuring XUI integration.

Creating Compatible Service Scripts

xOTT Panel uses universal service scripts that can support any streaming platform. This guide shows you how to create compatible service scripts for new platforms.

Script Structure

All service scripts must follow this standardized format:

#!/usr/bin/env python3
"""
Service Script Template - Standardized Format
=============================================

This script provides a standardized interface for service integration.
It follows the platform's service script conventions for seamless integration.

Required Actions:
- login: Authenticate user and store tokens
- refresh: Refresh authentication tokens
- channels: Get available channels list
- manifest: Get stream manifest URL
- cdm: Get DRM decryption keys
- vod_categories: Get VOD content categories
- vod_content: Get VOD content for a category
- vod_seasons: Get seasons for a series
- vod_episodes: Get episodes for a season
- vod_manifest: Get VOD manifest URL
- vod_cdm: Get DRM decryption keys for VOD

Standard Parameters:
- user: Username for authentication
- password: Password for authentication
- action: Action to perform
- id: Channel/Video ID for manifest/cdm actions
- category: VOD category
- page: Page number for pagination (default: 1)
- limit: Items per page (default: 20)
- proxy: Optional proxy URL
"""

import sys
import os
import json
import base64
import time
import uuid
import requests
import secrets
import string
from bs4 import BeautifulSoup
from pywidevine.cdm import Cdm
from pywidevine.device import Device
from pywidevine.pssh import PSSH

# ============================================================================
# CONFIGURATION
# ============================================================================

# Service Configuration
SERVICE_NAME = "YourService"
SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))

# Global variables (will be set during execution)
user = None
password = None
action = None
id = None
proxy = None
req = None

# ============================================================================
# LOGGING
# ============================================================================

def log_info(message):
    """Log info message to stderr."""
    print(message, file=sys.stderr)

def log_error(message):
    """Log error message to stderr."""
    print(f"ERROR: {message}", file=sys.stderr)

# ============================================================================
# DRM/CDM FUNCTIONS
# ============================================================================

def do_cdm(pssh_data, license_url, token=None):
    """Get DRM decryption keys using Widevine CDM."""
    try:
        if not license_url:
            log_error("No license URL provided (DRM not enabled for this stream)")
            return None

        pssh_obj = PSSH(pssh_data)
        device = Device.load(os.path.join(os.path.dirname(__file__), 'WVD.wvd'))
        cdm = Cdm.from_device(device)
        session_id = cdm.open()
        challenge = cdm.get_license_challenge(session_id, pssh_obj)

        headers = {
            'content-type': 'application/octet-stream',
            'origin': 'https://your-service.com',
            'referer': 'https://your-service.com/',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        }
        
        if token:
            headers['authorization'] = f'Bearer {token}'

        license_response = req.post(license_url, headers=headers, data=challenge)
        
        if license_response.ok:
            cdm.parse_license(session_id, license_response.content)
            
            keys = []
            for key in cdm.get_keys(session_id):
                if key.type != 'SIGNING':
                    keys.append(f"{key.kid.hex}:{key.key.hex()}")
            
            cdm.close(session_id)
            return keys
        else:
            log_error("License request failed")
            return None
                    
    except Exception as e:
        log_error(f"CDM processing failed: {str(e)}")
        return None

# ============================================================================
# AUTHENTICATION
# ============================================================================

def do_login(username, password):
    """Handle login action."""
    try:
        # Your authentication logic here
        # Return authentication tokens or session data
        pass
    except Exception as e:
        log_error(f"Login failed: {str(e)}")
        return None

def do_refresh(token):
    """Handle token refresh action."""
    try:
        # Your token refresh logic here
        pass
    except Exception as e:
        log_error(f"Token refresh failed: {str(e)}")
        return None

# ============================================================================
# CONTENT RETRIEVAL
# ============================================================================

def get_channels(token):
    """Get available channels list."""
    try:
        # Your channels retrieval logic here
        # Return formatted channels data
        pass
    except Exception as e:
        log_error(f"Failed to get channels: {str(e)}")
        return None

def get_events(token):
    """Get available events list."""
    try:
        # Your events retrieval logic here
        # Return formatted events data
        pass
    except Exception as e:
        log_error(f"Failed to get events: {str(e)}")
        return None

def get_vod_categories(token):
    """Get VOD content categories."""
    try:
        # Your VOD categories logic here
        pass
    except Exception as e:
        log_error(f"Failed to get VOD categories: {str(e)}")
        return None

def get_vod_content(token, category, page=1, limit=20):
    """Get VOD content for a category."""
    try:
        # Your VOD content logic here
        pass
    except Exception as e:
        log_error(f"Failed to get VOD content: {str(e)}")
        return None

# ============================================================================
# STREAMING
# ============================================================================

def get_manifest(token, channel_id):
    """Get stream manifest URL."""
    try:
        # Your manifest retrieval logic here
        # Return manifest URL and DRM info if applicable
        pass
    except Exception as e:
        log_error(f"Failed to get manifest: {str(e)}")
        return None

def get_vod_manifest(token, content_id):
    """Get VOD manifest URL."""
    try:
        # Your VOD manifest logic here
        pass
    except Exception as e:
        log_error(f"Failed to get VOD manifest: {str(e)}")
        return None

# ============================================================================
# MAIN EXECUTION
# ============================================================================

def main():
    global user, password, action, id, proxy, req
    
    # Parse command line arguments
    args = sys.argv[1:]
    for i in range(0, len(args), 2):
        if i + 1 < len(args):
            key = args[i].replace('--', '')
            value = args[i + 1]
            
            if key == 'user':
                user = value
            elif key == 'password':
                password = value
            elif key == 'action':
                action = value
            elif key == 'id':
                id = value
            elif key == 'proxy':
                proxy = value
    
    # Create requests session with proxy if provided
    req = requests.Session()
    if proxy:
        req.proxies = {'http': proxy, 'https': proxy}
    
    # Execute action based on input
    try:
        if action == 'login':
            result = do_login(user, password)
        elif action == 'refresh':
            result = do_refresh(user)  # user contains token in refresh action
        elif action == 'channels':
            result = get_channels(user)  # user contains token in channels action
        elif action == 'events':
            result = get_events(user)  # user contains token in events action
        elif action == 'manifest':
            result = get_manifest(user, id)  # user contains token, id contains channel_id
        elif action == 'cdm':
            result = do_cdm(user, password, id)  # user contains pssh, password contains license_url, id contains token
        elif action == 'vod_categories':
            result = get_vod_categories(user)  # user contains token
        elif action == 'vod_content':
            result = get_vod_content(user, password, id)  # user contains token, password contains category, id contains page
        elif action == 'vod_manifest':
            result = get_vod_manifest(user, id)  # user contains token, id contains content_id
        elif action == 'vod_cdm':
            result = do_cdm(user, password, id)  # user contains pssh, password contains license_url, id contains token
        else:
            log_error(f"Unknown action: {action}")
            sys.exit(1)
        
        if result:
            print(json.dumps(result, indent=2))
        else:
            log_error("Action failed")
            sys.exit(1)
            
    except Exception as e:
        log_error(f"Execution failed: {str(e)}")
        sys.exit(1)

if __name__ == "__main__":
    main()

Required Actions

Your service script must implement these actions:

login

Authenticate user and return authentication tokens

refresh

Refresh authentication tokens when they expire

channels

Return list of available live channels

events

Return list of available events

manifest

Get stream manifest URL for a channel

cdm

Get DRM decryption keys for protected content

vod_categories

Get VOD content categories

vod_content

Get VOD content for a category

vod_manifest

Get VOD manifest URL

vod_cdm

Get DRM decryption keys for VOD content

DRM Support

For DRM-protected content, include Widevine device files (.wvd) in your script directory. The script should extract PSSH data from manifests and request decryption keys from license servers.

Testing Your Script

Test your script using the command line:

python3 YourService.py --action login --user "username" --password "password"
python3 YourService.py --action channels --user "token"
python3 YourService.py --action manifest --user "token" --id "channel_id"

Setting Up Telegram Notifications

xOTT Panel includes a comprehensive Telegram notification system for real-time alerts about events, service status updates, proxy assignments, and system monitoring.

Step 1: Create a Telegram Bot

  1. Open Telegram and search for @BotFather
  2. Send /newbot command
  3. Follow the instructions to create your bot
  4. Save the bot token provided by BotFather

Step 2: Get Your Chat ID

  1. Send a message to your bot
  2. Visit: https://api.telegram.org/bot{YOUR_BOT_TOKEN}/getUpdates
  3. Find your chat ID in the response

Step 3: Configure in xOTT Panel

  1. Log in to your xOTT Panel dashboard
  2. Navigate to SettingsNotifications
  3. Enable Telegram Notifications
  4. Enter your Bot Token
  5. Enter your Chat ID
  6. Configure notification types:
    • Stream Alerts
    • Event Notifications
    • Service Status Updates
    • Proxy Assignment Updates
    • System Monitoring Alerts
  7. Click Save Settings

Notification Types

Event Notifications

Real-time alerts when events start, stop, or restart

Service Notifications

Updates about service status changes and proxy assignments

Stream Alerts

Notifications about stream status and performance

System Monitoring

Alerts about system health and resource usage

Testing Notifications

After configuration, test your notifications by:

  1. Starting a test stream
  2. Scheduling a test event
  3. Changing service proxy assignments
Security Note: Keep your bot token and chat ID secure. Anyone with these credentials can send messages to your chat.

XUI Panel Integration Setup

xOTT Panel includes full XUI Panel integration with automatic stream export, event scheduling, real-time synchronization, and centralized management.

Step 1: Prepare XUI Panel

  1. Ensure your XUI Panel is running and accessible
  2. Note your XUI Panel URL (e.g., https://your-xui-panel.com)
  3. Generate an access code from the Access Codes page in XUI Panel (Admin API access code)
  4. Generate an API key from the Profile Settings page in XUI Panel

Step 2: Configure XUI Connection

  1. Log in to your xOTT Panel dashboard
  2. Navigate to XUI Integration in the sidebar
  3. Click Add Connection
  4. Fill in the connection details:
    • Connection Name: Descriptive name for this connection
    • XUI Panel URL: Your XUI Panel base URL
    • Access Code: Access code generated from XUI Access Codes page (Admin API access code)
    • API Key: API key generated from XUI Profile Settings page
    • Auto-Sync: Enable automatic synchronization
  5. Click Test Connection to verify
  6. Click Save Connection

Step 3: Export Streams

  1. Navigate to Streams in xOTT Panel
  2. Select the streams you want to export
  3. Click Export to XUI
  4. Choose your XUI connection
  5. Configure export settings:
    • Stream name and description
    • Category assignment
    • Quality settings
    • Auto-activation
  6. Click Export

Step 4: Schedule Events

  1. Navigate to Events in xOTT Panel
  2. Create or select an event
  3. Click Export to XUI
  4. Configure event settings:
    • Event name and description
    • Start and end times
    • Stream assignment
    • Auto-activation schedule
  5. Click Schedule Export

Sync Status Monitoring

Monitor your XUI integration status through:

  • Sync Logs: View detailed sync operation logs
  • Status Dashboard: Real-time sync status overview
  • Error Handling: Automatic retry and error reporting
  • Notifications: Telegram alerts for sync events
Tip: Enable auto-sync for seamless operation. This ensures your XUI Panel stays updated automatically with any changes in xOTT Panel.