diff --git a/Services.md b/Services.md index ea5067a..f8687ab 100644 --- a/Services.md +++ b/Services.md @@ -9,6 +9,116 @@ own Services and only use unshackle with Services you have the legal right to do > unshackle repository as they both use the [Unlicense license] therefore direct reading and porting of their code would be > legal. +## Creating a Service + +To create a new service, you'll need to understand the basic structure and components. The best way to learn is by examining the included `EXAMPLE` service, which demonstrates all the core concepts and patterns used in unshackle services. + +### Service Structure + +Each service consists of two main files: + +1. **`__init__.py`** - Contains the main service class and logic +2. **`config.yaml`** - Contains service configuration (endpoints, client settings, etc.) + +### Service Directory Layout + +``` +unshackle/services/YOUR_SERVICE/ +├── __init__.py +└── config.yaml +``` + +### Key Components + +#### 1. Service Class + +Your service must inherit from the `Service` base class and implement several required methods: + +```python +from unshackle.core.service import Service + +class YOUR_SERVICE(Service): + """ + Service code for your-domain.com + Version: 1.0.0 + + Authorization: Cookies/Credentials + Security: FHD@L3/UHD@L1 + + Usage instructions here. + """ + + TITLE_RE = r"^(?:https?://?your-domain\.com/details/)?(?P[^/]+)" + GEOFENCE = ("US", "UK") # Optional: specify supported regions +``` + +#### 2. Required Methods + +- **`authenticate()`** - Handle authentication (cookies, credentials) +- **`search()`** - Search for content (returns SearchResult objects) +- **`get_titles()`** - Extract title metadata and return Movies/Series +- **`get_tracks()`** - Extract video/audio tracks from manifests +- **`get_widevine_license()`** - Handle Widevine DRM licensing +- **`get_playready_license()`** - Handle PlayReady DRM licensing (optional) +- **`get_chapters()`** - Extract chapter information (optional) + +#### 3. CLI Interface + +Each service needs a CLI command interface: + +```python +@staticmethod +@click.command(name="YOUR_SERVICE", short_help="https://your-domain.com") +@click.argument("title", type=str) +@click.option("-m", "--movie", is_flag=True, default=False, help="Specify if it's a movie") +@click.option("-d", "--device", type=str, default="android_tv", help="Select device from the config file") +@click.pass_context +def cli(ctx, **kwargs): + return YOUR_SERVICE(ctx, **kwargs) +``` + +### Configuration File + +The `config.yaml` file contains: + +```yaml +endpoints: + login: https://api.your-domain.com/v1/login + metadata: https://api.your-domain.com/v1/metadata/{title_id}.json + streams: https://api.your-domain.com/v1/streams + widevine_license: https://api.your-domain.com/v1/license/widevine + +client: + android_tv: + user_agent: USER_AGENT_STRING + license_user_agent: LICENSE_USER_AGENT_STRING + type: DEVICE_TYPE +``` + +### Study the EXAMPLE Service + +The `EXAMPLE` service (`unshackle/services/EXAMPLE/`) provides a complete, working template that demonstrates: + +- Cookie-based authentication with JWT tokens +- Token caching and refresh logic +- Search functionality +- Movie and series handling +- DASH manifest parsing +- Subtitle extraction +- Chapter extraction +- Both Widevine and PlayReady license handling + +### Getting Started + +1. Copy the `EXAMPLE` service directory to create your new service +2. Rename the directory and class to match your service +3. Update the configuration endpoints in `config.yaml` +4. Modify the authentication logic for your platform +5. Adjust the metadata parsing to match your API responses +6. Update the DRM license handling as needed + +The `EXAMPLE` service serves as both documentation and a functional template - study it carefully to understand the patterns and adapt them to your specific streaming platform. + ### Service Tags Service tags generally follow these rules: @@ -40,7 +150,7 @@ If you are collaborating with a team on multiple services then forking the proje 4. `git remote set-url --push upstream DISABLE` 5. `git fetch upstream` 6. `git pull upstream master` -7. (optionally) Hard reset to the latest stable version by tag. E.g., `git reset --hard v1.0.0`. +7. (optionally) Hard reset to the latest stable version by tag. E.g., `git reset --hard v1.0.1`. Now commit your Services or other changes to your forked repository. Once committed all your other team members can easily pull changes as well as push new changes. @@ -82,4 +192,4 @@ sure that the version of unshackle you have locally is supported by the Service > [!NOTE] > If you're using a cloud source that downloads the file once it gets opened, you don't have to worry as those will > automatically download. Python importing the files triggers the download to begin. However, it may cause a delay on -> startup. \ No newline at end of file +> startup.