### Example values.yaml for PlexAniSync Configuration Source: https://github.com/rickdb/plexanisync/blob/master/Helm/plexanisync/README.md Provides an example values.yaml file for configuring PlexAniSync, demonstrating settings for custom mappings, Plex and AniDB connection details, episode counting priority, rating synchronization, and scheduling. It also shows how to specify tokens for authentication. ```yaml custom_mappings: | remote-urls: - https://raw.githubusercontent.com/RickDB/PlexAniSync-Custom-Mappings/main/series-tvdb.en.yaml entries: - title: The Rising of the Shield Hero seasons: - season: 1 anilist-id: 99263 settings: plex_section: Anime|Anime Movies plex_url: https://plex.tld.org ani_username: UserName plex_episode_count_priority: true sync_ratings: false skip_list_update: true schedule: "* */1 * * *" tokens: ani: ani-token plex: plex-token ``` -------------------------------- ### Enable and Start Systemd Service and Timer Source: https://github.com/rickdb/plexanisync/wiki/Systemd-service These commands are used to reload the systemd daemon, enable the anilist-plex-sync service and timer to start on boot, and then start them immediately. This ensures the synchronization process runs as scheduled. ```shell sudo systemctl daemon-reload sudo systemctl enable anilist-plex-sync.service sudo systemctl start anilist-plex-sync.service sudo systemctl enable anilist-plex-sync.timer sudo systemctl start anilist-plex-sync.timer ``` -------------------------------- ### Install Project Requirements Source: https://github.com/rickdb/plexanisync/blob/master/README.md Installs the necessary Python packages for PlexAniSync using pip from a requirements file. Ensure you are in the project directory before running. ```bash pip install -r requirements.txt ``` -------------------------------- ### Start PlexAniSync Script Source: https://github.com/rickdb/plexanisync/blob/master/README.md Executes the main PlexAniSync script to start the synchronization process. The script may take time depending on library size and server performance. For automated syncing, consider using cron jobs or systemd timers. ```bash python PlexAniSync.py ``` -------------------------------- ### Custom Anime Mapping with GUID (YAML) Source: https://github.com/rickdb/plexanisync/blob/master/README.md Handles Plex shows and movies with duplicate titles by using the `guid` field for precise identification. The `guid` overrides `title` and `synonyms`. The format for Plex GUIDs is `plex://show/{id}` or `plex://movie/{id}`. ```yaml - title: "Rurouni Kenshin" guid: plex://show/5d9c07ece264b7001fc38094 seasons: - season: 1 anilist-id: 45 - season: 2 anilist-id: 45 - season: 3 anilist-id: 45 ``` ```yaml - title: "Rurouni Kenshin (2023)" guid: plex://show/6330a57e9705fab2b34f656d seasons: - season: 1 anilist-id: 142877 ``` -------------------------------- ### PlexAniSync Configuration File (INI) Source: https://context7.com/rickdb/plexanisync/llms.txt Example configuration file ('settings.ini') for PlexAniSync, specifying Plex library sections and authentication methods. It includes placeholders for direct connection details (URL, token) or details for MyPlex authentication. ```ini # settings.ini [PLEX] # Library section name(s) - use pipe (|) for multiple anime_section = Anime|Anime Movies # Authentication: 'direct' or 'myplex' authentication_method = myplex # ===== Direct Authentication ===== base_url = http://192.168.1.100:32400 token = your_plex_token_here ``` -------------------------------- ### Plex Server Direct Authentication (Python) Source: https://context7.com/rickdb/plexanisync/llms.txt This Python snippet demonstrates the initial setup for connecting directly to a Plex Media Server using its base URL and a Plex token. It imports necessary classes from `plexapi.server` and `requests` for establishing the connection. This is a prerequisite for further interactions with the Plex API. ```python from plexapi.server import PlexServer from requests import Session from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager ``` -------------------------------- ### Custom Mappings Volume Mount Example Source: https://github.com/rickdb/plexanisync/blob/master/Docker/PlexAniSync/README.md This example demonstrates how to mount a custom mappings YAML file into the PlexAniSync container. This allows users to override default anime mappings, and changes to the host file are reflected on the next container run without requiring a restart. ```bash -v /path/to/your/custom_mappings.yaml:/plexanisync/custom_mappings.yaml ``` -------------------------------- ### Docker Compose for Tautulli PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/Docker/Tautulli/README.md This Docker Compose configuration defines the Tautulli PlexAniSync service. It specifies the container name, image, restart policy, environment variables for configuration, volume mappings for persistence and custom settings, and port forwarding for accessing the service. Ensure to replace placeholder paths and tokens. ```yaml version: '3.7' services: plexanisync: container_name: tautulli-plexanisync image: 'ghcr.io/rickdb/tautulli-plexanisync:latest' restart: unless-stopped environment: - TZ= - PLEX_SECTION=Anime - 'PLEX_URL=http://127.0.0.1:32400' - PLEX_TOKEN=SomePlexToken - ANI_USERNAME=SomeUser - ANI_TOKEN=SomeToken volumes: - '/path/to/tautulli-data-directory:/config' - '/path/to/your/custom_mappings.yaml:/plexanisync/custom_mappings.yaml' ports: - '8181:8181' ``` -------------------------------- ### Docker Command for Tautulli PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/Docker/Tautulli/README.md This Docker command deploys the Tautulli PlexAniSync container. It requires setting environment variables for timezone, Plex details (URL, token), Anilist credentials (username, token), and mapping volumes for configuration and custom mappings. The container is exposed on port 8181 and restarts automatically. ```bash docker run -d \ --name=tautulli-plexanisync \ -e TZ= \ -e PLEX_SECTION=Anime \ -e PLEX_URL=http://127.0.0.1:32400 \ -e PLEX_TOKEN= \ -e ANI_USERNAME= \ -e ANI_TOKEN= \ -p 8181:8181 \ -v :/config \ -v :/plexanisync/custom_mappings.yaml \ --restart unless-stopped \ ghcr.io/rickdb/tautulli-plexanisync ``` -------------------------------- ### Systemd Timer Management Commands Source: https://context7.com/rickdb/plexanisync/llms.txt Bash commands to manage the PlexAniSync systemd timer, including reloading daemon, enabling, starting, checking status, and viewing logs. ```bash # Enable and start timer sudo systemctl daemon-reload sudo systemctl enable plexanisync.timer sudo systemctl start plexanisync.timer # Check status sudo systemctl status plexanisync.timer sudo systemctl list-timers # View logs journalctl -u plexanisync.service -f ``` -------------------------------- ### Systemd Timer for PlexAniSync Scheduling Source: https://context7.com/rickdb/plexanisync/llms.txt Systemd timer unit file to schedule the execution of the PlexAniSync service. This example triggers the service on boot and then every 30 minutes. ```systemd # /etc/systemd/system/plexanisync.timer [Unit] Description=PlexAniSync Timer Requires=plexanisync.service [Timer] OnBootSec=5min OnUnitActiveSec=30min Persistent=true [Install] WantedBy=timers.target ``` -------------------------------- ### Custom Mappings Configuration (YAML) Source: https://github.com/rickdb/plexanisync/blob/master/Helm/plexanisync/README.md This snippet demonstrates how to configure custom mappings for plexanisync using a multiline YAML string. It specifies the `custom_mappings` parameter and provides an example of including remote YAML files for series and movie data. ```yaml custom_mappings: | remote-urls: - https://raw.githubusercontent.com/RickDB/PlexAniSync-Custom-Mappings/main/series-tvdb.en.yaml - https://raw.githubusercontent.com/RickDB/PlexAniSync-Custom-Mappings/main/movies-tmdb.en.yaml ``` -------------------------------- ### Set Resource Requests and Limits for PlexAniSync Container Source: https://github.com/rickdb/plexanisync/blob/master/Helm/plexanisync/README.md Defines the CPU and memory resource requests and limits for the plexanisync container. This is crucial for managing resource consumption in containerized environments. Example shows requests for 100m CPU and 256Mi memory, with limits of 1 CPU and 1Gi memory. ```yaml resources: limits: cpu: '1' memory: 1Gi requests: cpu: '100m' memory: 256Mi ``` -------------------------------- ### Define Environment Variables for PlexAniSync Container Source: https://github.com/rickdb/plexanisync/blob/master/Helm/plexanisync/README.md This section describes how to define additional environment variables for the plexanisync container. These are provided as a list of key-value pairs, similar to Kubernetes EnvVar definitions. Example shows a single environment variable 'KEY' with value 'VALUE'. ```yaml envVars: - name: KEY value: "VALUE" ``` -------------------------------- ### Custom Anime Mappings Configuration (YAML) Source: https://context7.com/rickdb/plexanisync/llms.txt This YAML file defines custom mappings for anime to link Plex seasons with specific AniList entries. It supports various mapping scenarios including simple season-to-entry, split seasons, multi-season series, long-running series, duplicate titles using GUIDs, and synonyms. ```yaml # custom_mappings.yaml # Remote community mappings (optional) remote-urls: - https://raw.githubusercontent.com/RickDB/PlexAniSync-Custom-Mappings/main/series-tvdb.en.yaml entries: # Simple mapping: 1 Plex season → 1 AniList entry - title: The Rising of the Shield Hero seasons: - season: 1 anilist-id: 99263 # Split season: 1 Plex season → 2 AniList entries - title: "Re:ZERO -Starting Life in Another World-" seasons: - season: 2 anilist-id: 108632 # Episodes 1-13 start: 1 - season: 2 anilist-id: 119661 # Episodes 14+ start: 14 # Multi-season series - title: "Code Geass: Lelouch of the Rebellion" seasons: - season: 1 anilist-id: 1575 - season: 2 anilist-id: 2904 # Long-running series (multiple Plex seasons → same AniList ID) - title: Gintama seasons: - season: 1 anilist-id: 918 - season: 2 anilist-id: 918 - season: 3 anilist-id: 918 - season: 4 anilist-id: 918 - season: 5 anilist-id: 9969 # Duplicate titles (use GUID for disambiguation) - title: "Rurouni Kenshin" guid: plex://show/5d9c07ece264b7001fc38094 seasons: - season: 1 anilist-id: 45 - title: "Rurouni Kenshin (2023)" guid: plex://show/6330a57e9705fab2b34f656d seasons: - season: 1 anilist-id: 142877 # Synonyms (alternative titles) - title: 'Shaman King (2021)' synonyms: - 'Shaman King' seasons: - season: 1 anilist-id: 119675 ``` -------------------------------- ### Tautulli Sync Helper with Alternate Settings Source: https://github.com/rickdb/plexanisync/blob/master/README.md Executes the Tautulli Sync Helper script, specifying an alternate settings file and the Plex show name as arguments. This enables customized synchronization for Tautulli data. ```bash python TautulliSyncHelper.py settings_alternate.ini ``` -------------------------------- ### Docker Deployment for PlexAniSync Source: https://context7.com/rickdb/plexanisync/llms.txt Commands for deploying PlexAniSync using Docker, including pulling the image, creating a settings file, running the container, and viewing logs. ```bash # Pull image docker pull ghcr.io/rickdb/plexanisync:latest # Create settings file on host cat > /path/to/settings.ini << EOF [PLEX] anime_section = Anime authentication_method = myplex server = MyServer myplex_user = username myplex_token = token [ANILIST] username = anilist_user access_token = long_token_here EOF # Run container (syncs every 30 minutes) docker run -d \ --name plexanisync \ -v /path/to/settings.ini:/plexanisync/settings.ini:ro \ -v /path/to/custom_mappings.yaml:/plexanisync/custom_mappings.yaml:ro \ -e SETTINGS_FILE=/plexanisync/settings.ini \ -e SYNC_INTERVAL=1800 \ --restart unless-stopped \ ghcr.io/rickdb/plexanisync:latest # View logs docker logs -f plexanisync # Manual sync docker exec plexanisync python PlexAniSync.py ``` -------------------------------- ### Specify Alternate Settings File Source: https://github.com/rickdb/plexanisync/blob/master/README.md Allows PlexAniSync to load configuration from a specified INI file instead of the default `settings.in`. This is useful for managing different configurations. ```bash python PlexAniSync.py settings_alternate.ini ``` -------------------------------- ### Full Sync Workflow (Python) Source: https://context7.com/rickdb/plexanisync/llms.txt Orchestrates a complete synchronization process from Plex to AniList. It loads configuration, initializes AniList and Plex modules, retrieves data from both services, matches watched status, and updates AniList accordingly. Requires 'settings.ini' for configuration. ```python import configparser import logging from plexanisync.anilist import Anilist from plexanisync.custom_mappings import read_custom_mappings from plexanisync.plexmodule import PlexModule # Load configuration settings = configparser.ConfigParser() settings.read("settings.ini", encoding="utf-8") anilist_settings = settings["ANILIST"] plex_settings = settings["PLEX"] # Setup logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger("PlexAniSync") # Load custom mappings custom_mappings = read_custom_mappings() logger.info(f"Loaded {len(custom_mappings)} custom mappings") # Initialize AniList anilist = Anilist(anilist_settings, custom_mappings) anilist_series = anilist.process_user_list() if not anilist_series: logger.error("Failed to retrieve AniList list") exit(1) logger.info(f"Retrieved {len(anilist_series)} series from AniList") # Initialize Plex plexmodule = PlexModule(plex_settings) plex_anime_shows = plexmodule.get_anime_shows() if not plex_anime_shows: logger.error("No anime shows found in Plex") exit(1) logger.info(f"Found {len(plex_anime_shows)} shows in Plex") # Extract watch data plex_watched = plexmodule.get_watched_shows(plex_anime_shows) if not plex_watched: logger.error("No watched shows found") exit(1) logger.info(f"Found {len(plex_watched)} watched shows") # Match and sync anilist.match_to_plex(anilist_series, plex_watched) logger.info("Sync complete") ``` -------------------------------- ### Direct Plex Authentication Configuration for PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/README.md This configuration block demonstrates how to set up direct Plex authentication for PlexAniSync. It's intended for advanced users who prefer not to use Plex's online authentication. It requires the full Plex site URL (`base_url`) and a manually obtained Plex token. ```ini [PLEX] anime_section = Anime authentication_method = direct base_url = http://192.168.1.234:32400 token = abcdef123456789 ``` -------------------------------- ### PlexAniSync Configuration File Source: https://context7.com/rickdb/plexanisync/llms.txt Configuration settings for PlexAniSync, including MyPlex authentication, AniList credentials, and optional sync behaviors. ```ini [PLEX] server = MyServerName myplex_user = your_username myplex_token = your_myplex_token # Alternative: myplex_password = your_password # ===== Plex Home User Sync (Optional) ===== home_user_sync = False home_username = ManagedUserName home_server_base_url = http://192.168.1.100:32400 [ANILIST] # AniList username (not email) username = YourAniListUsername # OAuth access token (valid 1 year) # Get from: https://anilist.co/api/v2/oauth/authorize?client_id=1549&response_type=token access_token = eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6Ij... # ===== Optional Settings ===== # Force Plex episode count to override AniList (use with caution) plex_episode_count_priority = False # Test mode - match shows but don't update AniList skip_list_update = False # Log shows that couldn't be matched to failed_matches.txt log_failed_matches = False # Sync Plex ratings (1-5 stars) to AniList scores (0-100) sync_ratings = False ``` -------------------------------- ### Plex Server Authentication (Direct) Source: https://context7.com/rickdb/plexanisync/llms.txt Details on how to authenticate directly with a Plex Media Server using its base URL and a Plex token. ```APIDOC ## Plex Server Authentication (Direct) ### Description This section outlines the process for establishing a direct connection to your Plex Media Server. It involves providing the server's base URL and a Plex authentication token. ### Method N/A (Configuration setting) ### Endpoint N/A ### Parameters #### Configuration - **Plex URL** (string) - Required - The base URL of your Plex Media Server (e.g., `http://[PLEX_IP_ADDRESS]:32400`). - **Plex Token** (string) - Required - Your Plex authentication token, which can be found in your Plex account settings under "Network" or by inspecting network requests. ### Usage Example (Python `plexapi`) ```python from plexapi.server import PlexServer PLEX_URL = 'http://[PLEX_IP_ADDRESS]:32400' PLEX_TOKEN = 'YOUR_PLEX_TOKEN' plex = PlexServer(PLEX_URL, PLEX_TOKEN) # Now you can interact with your Plex server, e.g.: # print(plex.library.section('Anime').all()) ``` ``` -------------------------------- ### MyPlex Authentication Configuration for PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/README.md This configuration block shows how to set up MyPlex authentication for PlexAniSync. It requires the Plex server name, username, and a Plex token. It also supports syncing with a specific Plex Home user by enabling `home_user_sync` and providing the `home_username` and `home_server_base_url`. ```ini [PLEX] anime_section = Anime authentication_method = myplex server = Sadala myplex_user = Goku myplex_token = abcdef123456789 # Optional: Sync with a specific Plex Home user # home_user_sync = True # home_username = Megumin # home_server_base_url = http://127.0.0.1:32400 ``` -------------------------------- ### AniList Authentication Configuration for PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/README.md This configuration block details how to set up AniList authentication for PlexAniSync. It requires an AniList `access_token` obtained from the AniList API and the user's AniList username. ```ini [ANILIST] username = GoblinSlayer access_token = iLikeToastyGoblins. ``` -------------------------------- ### Fetch AniList User Library Data (Python) Source: https://context7.com/rickdb/plexanisync/llms.txt This Python code fetches a user's complete anime list from AniList, including watch progress and metadata, using the AniList GraphQL API. It utilizes `sgqlc` for GraphQL operations and `RequestsEndpoint` for communication. The query retrieves entry IDs, progress, status, scores, and media details like titles and episode counts. Ensure `access_token` is correctly set. ```python from sgqlc.endpoint.requests import RequestsEndpoint from sgqlc.operation import Operation from plexanisync.anilist_schema import anilist_schema as schema access_token = "YOUR_ANILIST_ACCESS_TOKEN" endpoint = RequestsEndpoint( url="https://graphql.anilist.co", base_headers={ "Authorization": f"Bearer {access_token}", "Accept": "application/json", "Content-Type": "application/json" } ) # GraphQL query operation = Operation(schema.Query) collection = operation.media_list_collection(userName="YourUsername", type="ANIME") lists = collection.lists() entries = lists.entries() entries.id() entries.progress() entries.status() entries.score(format="POINT_100") media = entries.media() media.id() media.episodes() media.title.romaji() media.title.english() media.start_date.year() data = endpoint(operation) # Returns: List of anime with progress tracking # Example entry: {id: 20, progress: 220, status: "COMPLETED", media: {title: "Naruto", episodes: 220}} ``` -------------------------------- ### Custom Anime Mapping Configuration (YAML) Source: https://github.com/rickdb/plexanisync/blob/master/README.md Defines custom mappings between Plex titles/seasons and AniList series IDs. This format allows for precise synchronization, especially for series with multiple seasons or split seasons. Ensure YAML syntax is correct, particularly with special characters in titles. ```yaml - title: "Plex title for series" seasons: - season: Plex season anilist-id: AniList series ID - season: Plex season anilist-id: AniList series ID ``` ```yaml - title: "Re:ZERO -Starting Life in Another World-" seasons: - season: 2 anilist-id: 108632 start: 1 - season: 2 anilist-id: 119661 start: 14 ``` -------------------------------- ### Fetch User's AniList Library Source: https://context7.com/rickdb/plexanisync/llms.txt Retrieves the complete anime list for a user from AniList, including watch progress, status, scores, and media metadata. This uses a GraphQL query. ```APIDOC ## Fetch User's AniList Library ### Description This endpoint uses GraphQL to fetch a user's entire anime list from AniList, providing details on each entry's watch progress, status, score, and basic media information. ### Method POST ### Endpoint `https://graphql.anilist.co` ### Headers - **Authorization** (string) - Required - `Bearer YOUR_ACCESS_TOKEN` - **Accept** (string) - Required - `application/json` - **Content-Type** (string) - Required - `application/json` ### Request Body ```json { "query": "query mediaListCollection($userName: String) {\n MediaListCollection(userName: $userName, type: ANIME) {\n lists {\n entries {\n id\n progress\n status\n score(format: POINT_100)\n media {\n id\n episodes\n title {\n romaji\n english\n }\n startDate {\n year\n }\n }\n }\n }\n }\n}", "variables": { "userName": "YourUsername" } } ``` ### Response #### Success Response (200) Returns a JSON object containing the user's AniList media collection. - **data.MediaListCollection.lists[].entries[]** (array) - A list of anime entries. - **id** (integer) - The AniList entry ID. - **progress** (integer) - The number of episodes watched. - **status** (string) - The watch status (e.g., "COMPLETED", "CURRENT"). - **score** (float) - The user's score for the anime (0-100). - **media** (object) - Information about the anime. - **id** (integer) - The AniList media ID. - **episodes** (integer) - The total number of episodes. - **title** (object) - **romaji** (string) - The Romaji title. - **english** (string) - The English title. - **startDate** (object) - **year** (integer) - The year the anime started airing. #### Response Example ```json { "data": { "MediaListCollection": { "lists": [ { "entries": [ { "id": 20, "progress": 220, "status": "COMPLETED", "score": 85.0, "media": { "id": 1000, "episodes": 220, "title": { "romaji": "Naruto", "english": "Naruto" }, "startDate": { "year": 2002 } } } ] } ] } } } ``` ``` -------------------------------- ### Tautulli Webhook Script Configuration Source: https://context7.com/rickdb/plexanisync/llms.txt Configuration steps for Tautulli to trigger PlexAniSync via webhook when playback stops. This involves setting up a script agent and defining arguments. ```bash # Tautulli Settings > Notification Agents > Scripts > Add a new notification agent # Script Folder: /path/to/PlexAniSync # Script File: ./TautulliSyncHelper.py (or TautulliSyncHelper.ps1 on Windows) # Triggers: Check "Playback Stop" # Script Arguments (Playback Stop): {show_name} # Advanced: # - Script Timeout: 300 seconds # - Save logs to file: enabled # Test by playing and stopping an anime episode in Plex # Check PlexAniSync.log for sync activity ``` -------------------------------- ### Plex Library Section Configuration for PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/README.md This configuration shows how to specify the Plex library section(s) containing Anime for PlexAniSync. A single section name can be provided, or multiple sections can be listed, separated by the pipe ('|') character. ```ini [PLEX] anime_section = Anime ``` ```ini [PLEX] anime_section = Anime|Anime2 ``` -------------------------------- ### AniList OAuth Token Retrieval Source: https://context7.com/rickdb/plexanisync/llms.txt Details on how to obtain and configure AniList OAuth2 bearer tokens for authentication. Includes the authorization URL, callback format, and configuration in settings.ini. ```APIDOC ## AniList OAuth Token Retrieval ### Description Authentication with AniList requires a bearer token obtained through OAuth2 flow. This section details the process of obtaining the token and storing it for use. ### Method GET (for initial authorization) ### Endpoint `https://anilist.co/api/v2/oauth/authorize?client_id=1549&response_type=token` ### Parameters #### Query Parameters - **client_id** (string) - Required - The client ID for the application. - **response_type** (string) - Required - Must be 'token' for implicit grant flow. ### Callback URL Upon successful authorization, the user is redirected to a callback URL containing the access token: `https://anilist.co/api/v2/auth/callback#access_token=YOUR_TOKEN&token_type=Bearer&expires_in=31536000` ### Configuration The obtained `access_token` should be stored in the `settings.ini` file under the `[ANILIST]` section. ```ini [ANILIST] username = YourUsername access_token = YOUR_OBTAINED_ACCESS_TOKEN ``` ### Token Validation The application automatically validates the token's expiry on startup. The following Python snippet demonstrates how to check token expiry manually: ```python import base64 import json from datetime import datetime def check_token_expiry(anilist_token): try: base64_body = anilist_token.split(".")[1] + "==" token_body = json.loads(base64.urlsafe_b64decode(base64_body)) token_expiry = int(token_body["exp"]) if datetime.fromtimestamp(token_expiry) < datetime.now(): raise RuntimeError("Anilist token is expired") return True except Exception as e: print(f"Error checking token expiry: {e}") return False ``` ``` -------------------------------- ### Systemd Service for PlexAniSync Source: https://context7.com/rickdb/plexanisync/llms.txt Systemd service unit file to define how PlexAniSync runs as a background service on Linux systems. It specifies the user, working directory, and execution command. ```systemd # /etc/systemd/system/plexanisync.service [Unit] Description=PlexAniSync Service After=network.target [Service] Type=oneshot User=your_username WorkingDirectory=/home/your_username/PlexAniSync ExecStart=/usr/bin/python3 /home/your_username/PlexAniSync/PlexAniSync.py StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target ``` -------------------------------- ### Single Show Sync via Tautulli (Python) Source: https://context7.com/rickdb/plexanisync/llms.txt Updates a single show's status on AniList, triggered by a Tautulli webhook. It takes the show name as a command-line argument and optionally a custom settings file. Includes a delay to ensure Plex processes playback events before syncing. ```python import sys import time import configparser from plexanisync.anilist import Anilist from plexanisync.custom_mappings import read_custom_mappings from plexanisync.plexmodule import PlexModule # Get show name from command line if len(sys.argv) < 2: print("Usage: python TautulliSyncHelper.py ") sys.exit(1) show_name = sys.argv[1] # Optional: custom settings file settings_file = sys.argv[2] if len(sys.argv) > 2 else "settings.ini" # Wait 5 seconds for Plex to process the playback stop time.sleep(5) # Load settings settings = configparser.ConfigParser() settings.read(settings_file) anilist_settings = settings["ANILIST"] plex_settings = settings["PLEX"] # Initialize custom_mappings = read_custom_mappings() anilist = Anilist(anilist_settings, custom_mappings) anilist_series = anilist.process_user_list() # Get specific show from Plex plexmodule = PlexModule(plex_settings) plex_shows = plexmodule.get_anime_shows_filter(show_name) if not plex_shows: print(f"Show not found: {show_name}") sys.exit(1) # Get watch data and sync plex_watched = plexmodule.get_watched_shows(plex_shows) if plex_watched: anilist.match_to_plex(anilist_series, plex_watched) print(f"Synced: {show_name}") else: print(f"No watched data for: {show_name}") ``` -------------------------------- ### Configure PlexAniSync Container Image Source: https://github.com/rickdb/plexanisync/blob/master/Helm/plexanisync/README.md Specifies the container image to be used for PlexAniSync. The default image is ghcr.io/rickdb/plexanisync with the 'latest' tag. This allows users to pin to a specific version or use a custom build. ```yaml image: ghcr.io/rickdb/plexanisync:latest ``` -------------------------------- ### Configure PlexAniSync Settings Source: https://github.com/rickdb/plexanisync/blob/master/Helm/plexanisync/README.md Configures various settings for PlexAniSync, including Plex section mapping, Plex URL, Anilist username, episode count priority, rating synchronization, skipping list updates, and scheduling. The 'settings.schedule' parameter uses cron syntax. ```yaml settings: plex_section: Anime|Anime Movies plex_url: https://plex.tld.org ani_username: username plex_episode_count_priority: true sync_ratings: false skip_list_update: true schedule: "* */1 * * *" ``` -------------------------------- ### Connect to Plex Server with Self-Signed SSL Certificate Source: https://context7.com/rickdb/plexanisync/llms.txt Establishes a connection to a Plex Media Server using its IP address and token. It includes a custom HTTP adapter to ignore SSL certificate host name verification, which is useful for self-signed certificates. ```python from plexapi.server import PlexServer from requests import Session from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager class HostNameIgnoringAdapter(HTTPAdapter): def init_poolmanager(self, connections, maxsize, block=..., **pool_kwargs): self.poolmanager = PoolManager( num_pools=connections, maxsize=maxsize, block=block, assert_hostname=False, **pool_kwargs ) session = Session() session.mount("https://", HostNameIgnoringAdapter()) # Configuration base_url = "http://192.168.1.234:32400" token = "your_plex_token_here" # Connect plex = PlexServer(base_url, token, session) # Verify connection print(f"Connected to: {plex.friendlyName}") print(f"Version: {plex.version}") ``` -------------------------------- ### Define Plex and Anilist Tokens for PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/Helm/plexanisync/README.md Provides the necessary authentication tokens for Plex and Anilist. These tokens are essential for PlexAniSync to interact with both services. The structure defines separate keys for 'ani' (Anilist) and 'plex' tokens. ```yaml tokens: ani: ani-token plex: plex-token ``` -------------------------------- ### Check Systemd Timer Status Source: https://github.com/rickdb/plexanisync/wiki/Systemd-service This command lists all active systemd timers, allowing you to verify if the anilist-plex-sync timer is running and when it is scheduled to next activate. It provides a snapshot of the timer's status and remaining time. ```shell sudo systemctl list-timers ``` -------------------------------- ### Docker Compose Configuration for PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/Docker/PlexAniSync/README.md This Docker Compose configuration defines the PlexAniSync service. It specifies the container name, image, restart policy, environment variables for Plex and AniList integration, and volume mounts for time synchronization and custom mappings. ```yaml version: '3.7' services: plexanisync: container_name: plexanisync image: 'ghcr.io/rickdb/plexanisync:latest' restart: unless-stopped environment: - PLEX_SECTION=Anime|Anime Movies - 'PLEX_URL=http://127.0.0.1:32400' - PLEX_TOKEN=SomePlexToken - ANI_USERNAME=SomeUser - ANI_TOKEN=SomeToken - INTERVAL=3600 volumes: - '/etc/localtime:/etc/localtime:ro' - '/path/to/your/custom_mappings.yaml:/plexanisync/custom_mappings.yaml' ``` -------------------------------- ### Update AniList Watch Progress (Python) Source: https://context7.com/rickdb/plexanisync/llms.txt This Python function updates a single anime entry's watch progress and status on AniList using a GraphQL mutation. It includes optional score updates and implements rate limiting by pausing for 0.2 seconds between requests and handling `429` errors by retrying with a delay. Requires `sgqlc` and `time` modules. ```python from sgqlc.operation import Operation from plexanisync.anilist_schema import anilist_schema as schema import time def update_series(endpoint, media_id, progress, status, score_raw=None): operation = Operation(schema.Mutation) args = { 'mediaId': media_id, 'status': status, # "CURRENT", "COMPLETED", "PLANNING", "DROPPED", "PAUSED", "REPEATING" 'progress': progress } if score_raw is not None: args['scoreRaw'] = score_raw # 0-100 scale save = operation.save_media_list_entry(**args) save.id() save.progress() save.status() # Rate limiting: 200ms delay between requests time.sleep(0.2) try: data = endpoint(operation) return data except Exception as e: # Handle 429 rate limit if hasattr(e, 'response') and e.response.status_code == 429: retry_after = int(e.response.headers.get('retry-after', 60)) time.sleep(retry_after + 1) return update_series(endpoint, media_id, progress, status, score_raw) raise # Usage example # Assuming 'endpoint' is an initialized RequestsEndpoint object # update_series(endpoint, # media_id=20, # Naruto AniList ID # progress=220, # Episodes watched # status="COMPLETED", # score_raw=85) # Optional: 85/100 rating ``` -------------------------------- ### Retrieve Anime Shows from Plex Libraries Source: https://context7.com/rickdb/plexanisync/llms.txt Fetches all shows from specified Plex library sections, filtering for anime content. It supports retrieving shows from a single library or multiple libraries by specifying their names separated by a pipe symbol. ```python from plexapi.server import PlexServer plex = PlexServer(base_url, token, session) # Single library section_name = "Anime" anime_section = plex.library.section(section_name) shows = anime_section.search() print(f"Found {len(shows)} shows") for show in shows: print(f"Title: {show.title}, Year: {show.year}") # Multiple libraries (separated by pipe) section_names = "Anime|Anime Movies|OVA" all_shows = [] for section in section_names.split("|"): section_obj = plex.library.section(section.strip()) shows = section_obj.search() all_shows.extend(shows) print(f"Total shows across all sections: {len(all_shows)}") ``` -------------------------------- ### Update AniList Watch Progress Source: https://context7.com/rickdb/plexanisync/llms.txt Updates the watch progress, status, and optionally the score for a specific anime entry on AniList. Includes rate limiting handling. ```APIDOC ## Update AniList Watch Progress ### Description This mutation allows you to update the progress (episode count), status, and score for a specific anime entry on your AniList profile. It includes built-in rate limiting handling. ### Method POST ### Endpoint `https://graphql.anilist.co` ### Headers - **Authorization** (string) - Required - `Bearer YOUR_ACCESS_TOKEN` - **Accept** (string) - Required - `application/json` - **Content-Type** (string) - Required - `application/json` ### Parameters #### Request Body (JSON Payload) - **query**: The GraphQL mutation string. - **variables**: An object containing the variables for the mutation. - **mediaId** (integer) - Required - The AniList media ID of the anime to update. - **progress** (integer) - Required - The new episode count. - **status** (string) - Required - The new watch status. Options: `"CURRENT"`, `"COMPLETED"`, `"PLANNING"`, `"DROPPED"`, `"PAUSED"`, `"REPEATING"`. - **scoreRaw** (float) - Optional - The new score for the anime on a 0-100 scale. ### Request Example ```json { "query": "mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $scoreRaw: Int) {\n SaveMediaListEntry(mediaId: $mediaId, progress: $progress, status: $status, scoreRaw: $scoreRaw) {\n id\n progress\n status\n }\n}", "variables": { "mediaId": 20, "progress": 220, "status": "COMPLETED", "scoreRaw": 85 } } ``` ### Response #### Success Response (200) Returns a JSON object confirming the update. - **data.SaveMediaListEntry** (object) - Details of the saved entry. - **id** (integer) - The AniList entry ID. - **progress** (integer) - The updated episode count. - **status** (string) - The updated watch status. #### Response Example ```json { "data": { "SaveMediaListEntry": { "id": 12345, "progress": 220, "status": "COMPLETED" } } } ``` ### Rate Limiting If a 429 (Too Many Requests) error is received, the API will wait for the duration specified in the `retry-after` header before retrying the request. ``` -------------------------------- ### CronJob Defaults for PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/Helm/plexanisync/README.md Defines the default cron job configuration for PlexAniSync, specifying concurrency policy, and history limits for failed and successful jobs. This ensures scheduled synchronization occurs as intended. ```yaml cronjob: concurrencyPolicy: Forbid failedJobsHistoryLimit: 2 startingDeadlineSeconds: 300 successfulJobsHistoryLimit: 1 ``` -------------------------------- ### Load and Parse Custom Mappings (Python) Source: https://context7.com/rickdb/plexanisync/llms.txt Loads and parses custom anime mappings from a YAML file, validating against a JSON schema. It handles multiple entries, seasons, and aliases, storing them in a dictionary for quick lookup. This function is crucial for customizing how Plex items map to AniList entries. ```python import os from ruyaml import YAML import json from jsonschema import validate from dataclasses import dataclass from typing import Dict, List @dataclass class AnilistCustomMapping: season: int anime_id: int start: int def read_custom_mappings() -> Dict[str, List[AnilistCustomMapping]]: mapping_file = "custom_mappings.yaml" if not os.path.isfile(mapping_file): return {} yaml = YAML(typ='safe') # Load schema for validation with open('custom_mappings_schema.json', 'r') as f: schema = json.load(f) # Load mappings with open(mapping_file, 'r') as f: data = yaml.load(f) # Validate validate(data, schema) # Parse into dictionary mappings = {} for entry in data.get('entries', []): title = entry['title'].lower() guid = entry.get('guid', '') season_mappings = [] for season in entry['seasons']: season_mappings.append(AnilistCustomMapping( season=season['season'], anime_id=season['anilist-id'], start=season.get('start', 1) )) # Store by GUID (highest priority) if guid: mappings[guid] = season_mappings # Store by title mappings[title] = season_mappings # Store by synonyms for synonym in entry.get('synonyms', []): mappings[synonym.lower()] = season_mappings return mappings # Usage mappings = read_custom_mappings() # Lookup by title naruto_mappings = mappings.get("naruto", []) for mapping in naruto_mappings: print(f"Season {mapping.season} → AniList ID {mapping.anime_id}") ``` -------------------------------- ### Docker Run Command for PlexAniSync Source: https://github.com/rickdb/plexanisync/blob/master/Docker/PlexAniSync/README.md This command runs the PlexAniSync Docker container in detached mode. It configures essential environment variables for connecting to Plex and AniList, sets up volume mounts for time synchronization and custom mappings, and ensures the container restarts automatically. ```bash docker run -d \ --name=plexanisync \ --restart unless-stopped \ -e PLEX_SECTION="Anime|Anime Movies" \ -e PLEX_URL=http://127.0.0.1:32400 \ -e PLEX_TOKEN=SomePlexToken \ -e ANI_USERNAME=SomeUser \ -e ANI_TOKEN=SomeToken \ -e INTERVAL=3600 \ -v /etc/localtime:/etc/localtime:ro \ -v /path/to/your/custom_mappings.yaml:/plexanisync/custom_mappings.yaml \ ghcr.io/rickdb/plexanisync:latest ``` -------------------------------- ### Sync Plex Home User Watch Data Source: https://context7.com/rickdb/plexanisync/llms.txt Synchronizes watch data for specific Plex Home managed users. This script connects as an admin user to retrieve a home user's token and then connects as that home user to access their watch history. ```python from plexapi.myplex import MyPlexAccount from plexapi.server import PlexServer from requests import Session session = Session() # Admin credentials admin_user = "admin_username" admin_token = "admin_token" home_username = "HomeUserName" server_url = "http://127.0.0.1:32400" # Authenticate as admin admin_account = MyPlexAccount(admin_user, token=admin_token) admin_server = PlexServer(server_url, admin_account.authenticationToken, session) # Get home user information home_user_account = admin_account.user(home_username) # Retrieve home user's token for this server home_user_token = home_user_account.get_token(admin_server.machineIdentifier) # Connect as home user plex = PlexServer(server_url, home_user_token, session) print(f"Connected as home user: {home_username}") # Now all queries return home user's watch data ``` -------------------------------- ### Plex Server Authentication via MyPlex Source: https://context7.com/rickdb/plexanisync/llms.txt Authenticates to a Plex Media Server remotely using MyPlex cloud-based authentication. This method requires your Plex username and MyPlex token (or password) and the name of the server you wish to connect to. ```python from plexapi.myplex import MyPlexAccount from requests import Session session = Session() # Standard user authentication plex_user = "your_username" plex_token = "your_myplex_token" # or use plex_password plex_server_name = "MyPlexServer" account = MyPlexAccount(plex_user, token=plex_token, session=session) plex = account.resource(plex_server_name).connect() print(f"Authenticated to: {plex.friendlyName}") ``` -------------------------------- ### Map Custom settings.ini for Plex-AniSync Source: https://github.com/rickdb/plexanisync/blob/master/Docker/PlexAniSync/README.md This snippet demonstrates how to map a custom settings.ini file into the Plex-AniSync container and set the necessary environment variable to use it for alternative Plex login mechanisms. It assumes the settings file is located locally at '/docker/plexanisync/settings.ini' and maps it to '/config/settings.ini' within the container. The ':ro' flag ensures the file is mounted read-only. ```bash -v '/docker/plexanisync/settings.ini:/config/settings.ini:ro' -e 'SETTINGS_FILE=/config/settings.ini' ```