make instanceB path optional; add test run flag

pull/42/head
Junkbite 4 years ago
parent 0a867930b4
commit bc807c5b43

@ -9,7 +9,7 @@ Syncs two Radarr/Sonarr/Lidarr servers through the web API. Useful for syncing a
* Support two way sync (one way by default)
* Set language profiles (Sonarr v3 only)
* Filter syncing by content file quality (Radarr only)
* Filter syncing by tags (Sonarr only)
* Filter syncing by tags (Sonarr/Radarr v3 only)
## Configuration
@ -24,7 +24,7 @@ Syncs two Radarr/Sonarr/Lidarr servers through the web API. Useful for syncing a
url = http://127.0.0.1:8080
key = XXXXX
profile = 1080p
path = /data/Movies
path = /data/Movies # if not given will use RadarrA path for each movie - may not be what you want!
```
3. Or if you want to sync two Sonarr instances:
```ini
@ -60,8 +60,8 @@ Syncs two Radarr/Sonarr/Lidarr servers through the web API. Useful for syncing a
key = XXXXX
profile_filter = 1080p # add a filter to only sync contents belonging to this profile (can set by profile_filter_id as well)
quality_match = HD- # (Radarr only) regex match to only sync content that matches the set quality (ie if set to 1080p then only movies with matching downloaded quality of 1080p will be synced)
tag_filter = Horror # (Sonarr only) sync movies by tag name (seperate multiple tags by comma (no spaces) ie horror,comedy,action)
tag_filter_id = 2 # (Sonarr only) sync movies by tag id (seperate multiple tags by comma (no spaces) ie 2,3,4)
tag_filter = Horror # (Sonarr/Radarr v3 only) sync movies by tag name (seperate multiple tags by comma (no spaces) ie horror,comedy,action)
tag_filter_id = 2 # (Sonarr/Radarr v3 only) sync movies by tag id (seperate multiple tags by comma (no spaces) ie 2,3,4)
[*arrB]
url = http://127.0.0.1:8080
@ -74,6 +74,7 @@ Syncs two Radarr/Sonarr/Lidarr servers through the web API. Useful for syncing a
sync_bidirectionally = 1 # sync from instance A to B **AND** instance B to A
auto_search = 0 # search is automatically started on new content - disable by setting to 0 (default 1)
monitor_new_content = 0 # set to 0 to never monitor new content synced or to 1 to always monitor new content synced (default 1)
test_run = 1 # enable test mode - will run through sync program but will not actually sync content
```
**Note** If `sync_bidirectionally` is set to `1`, then instance A will require either `profile_id` or `profile` AND `path` as well
@ -166,6 +167,7 @@ To filter by profile in docker use `ARR_A_PROFILE_FILTER` or `ARR_A_PROFILE_FILT
* Set if you want to NOT monitor new content with `SYNCARR_MONITOR_NEW_CONTENT=0` (default 1)
* Match regex quality profiles with `*ARR_A_QUALITY_MATCH` or `*ARR_B_QUALITY_MATCH`
* Filter by tag names or ids with `*ARR_A_TAG_FILTER` / `*ARR_B_TAG_FILTER` or `*ARR_A_TAG_FILTER_ID` / `*ARR_B_TAG_FILTER_ID`
* Enable test mode with `SYNCARR_TEST_RUN`
---
## Troubleshooting

@ -173,6 +173,16 @@ if monitor_new_content is not None:
else:
monitor_new_content = 1
# enable test mode
is_test_run = get_config_value('SYNCARR_TEST_RUN', 'test_run', 'general')
if is_test_run is not None:
try:
is_test_run = int(is_test_run)
except ValueError:
is_test_run = 0
else:
is_test_run = 0
########################################################################################################################
# setup logger
@ -451,6 +461,7 @@ logger.debug({
'is_sonarr': is_sonarr,
'is_lidarr': is_lidarr,
'is_radarr': is_radarr,
'monitor_new_content': monitor_new_content,
'sync_bidirectionally': sync_bidirectionally,

@ -8,6 +8,7 @@ import configparser
import sys
import time
import re
from os.path import basename
from config import (
instanceA_url, instanceA_key, instanceA_path, instanceA_profile,
@ -25,7 +26,7 @@ from config import (
is_in_docker, instance_sync_interval_seconds,
sync_bidirectionally, auto_search, monitor_new_content,
tested_api_version, api_version, V3_API_PATH,
tested_api_version, api_version, V3_API_PATH, is_test_run,
)
@ -192,7 +193,7 @@ def sync_servers(instanceA_contents, instanceB_language_id, instanceB_contentIds
instanceB_path, instanceB_profile_id, instanceA_profile_filter_id,
instanceB_session, instanceB_url, instanceB_key, instanceA_quality_match,
instanceA_tag_filter_id):
global is_radarr, is_sonarr
global is_radarr, is_sonarr, is_test_run
search_ids = []
# if given instance A profile id then we want to filter out content without that id
@ -203,6 +204,7 @@ def sync_servers(instanceA_contents, instanceB_language_id, instanceB_contentIds
for content in instanceA_contents:
if content[content_id_key] not in instanceB_contentIds:
title = content.get('title') or content.get('artistName')
instance_path = instanceB_path or basename(content.get('path'))
# if given this, we want to filter from instance by profile id
if instanceA_profile_filter_id:
@ -218,8 +220,8 @@ def sync_servers(instanceA_contents, instanceB_language_id, instanceB_contentIds
logging.debug(f'Skipping content {title} - mismatched content_quality {content_quality} with instanceA_quality_match {instanceA_quality_match}')
continue
# if given tag filter then filter by tag - (Sonarr only)
if is_sonarr and instanceA_tag_filter_id:
# if given tag filter then filter by tag - (Sonarr/Radarr v3 only)
if (is_sonarr or is_radarr) and instanceA_tag_filter_id:
content_tag_ids = content.get('tags')
if not (set(content_tag_ids) & set(instanceA_tag_filter_id)):
logging.debug(f'Skipping content {title} - mismatched content_tag_ids {content_tag_ids} with instanceA_tag_filter_id {instanceA_tag_filter_id}')
@ -229,24 +231,28 @@ def sync_servers(instanceA_contents, instanceB_language_id, instanceB_contentIds
# get the POST payload and sync content to instance B
payload = get_new_content_payload(
content=content,
instance_path=instanceB_path,
instance_profile_id=instanceB_profile_id,
instance_url=instanceB_url,
content=content,
instance_path=instance_path,
instance_profile_id=instanceB_profile_id,
instance_url=instanceB_url,
instance_language_id=instanceB_language_id,
)
instanceB_content_url = get_content_path(instanceB_url, instanceB_key)
sync_response = instanceB_session.post(instanceB_content_url, data=json.dumps(payload))
# check response and save content id for searching later on if success
if sync_response.status_code != 201 and sync_response.status_code != 200:
logger.error(f'server sync error for {title} - response: {sync_response.text}')
if is_test_run:
logging.info('content title "{0}" synced successfully (test only)'.format(title))
else:
try:
search_ids.append(int(sync_response.json()['id']))
except:
logger.error(f'Could not decode sync response from {instanceB_content_url}')
logging.info('content title "{0}" synced successfully'.format(title))
sync_response = instanceB_session.post(instanceB_content_url, data=json.dumps(payload))
# check response and save content id for searching later on if success
if sync_response.status_code != 201 and sync_response.status_code != 200:
logger.error(f'server sync error for {title} - response: {sync_response.text}')
else:
try:
search_ids.append(int(sync_response.json()['id']))
except:
logger.error(f'Could not decode sync response from {instanceB_content_url}')
logging.info('content title "{0}" synced successfully'.format(title))
logging.info(f'{len(search_ids)} contents synced successfully')
@ -321,7 +327,7 @@ def check_status(instance_session, instance_url, instance_key, instance_name='',
def sync_content():
global instanceA_profile_id, instanceA_profile, instanceB_profile_id, instanceB_profile, instanceA_profile_filter, instanceA_profile_filter_id, instanceB_profile_filter, instanceB_profile_filter_id, tested_api_version, instanceA_language_id, instanceA_language, instanceB_language_id, instanceB_language, instanceA_quality_match, instanceB_quality_match, is_sonarr, instanceA_tag_filter_id, instanceA_tag_filter, instanceB_tag_filter_id, instanceB_tag_filter
global instanceA_profile_id, instanceA_profile, instanceB_profile_id, instanceB_profile, instanceA_profile_filter, instanceA_profile_filter_id, instanceB_profile_filter, instanceB_profile_filter_id, tested_api_version, instanceA_language_id, instanceA_language, instanceB_language_id, instanceB_language, instanceA_quality_match, instanceB_quality_match, is_sonarr, instanceA_tag_filter_id, instanceA_tag_filter, instanceB_tag_filter_id, instanceB_tag_filter, is_radarr
# get sessions
instanceA_session = requests.Session()
@ -329,6 +335,7 @@ def sync_content():
instanceB_session = requests.Session()
instanceB_session.trust_env = False
# check if we tested if we are using v2 or v3
if not tested_api_version:
check_status(instanceA_session, instanceA_url, instanceA_key, instance_name='A')
check_status(instanceB_session, instanceB_url, instanceB_key, instance_name='B')
@ -359,7 +366,7 @@ def sync_content():
})
# do the same for tag id filters if they exist - (only Sonarr)
if is_sonarr:
if is_sonarr or is_radarr:
if not instanceA_tag_filter_id and instanceA_tag_filter:
instanceA_tag_filter_id = get_tag_from_id(instanceA_session, instanceA_url, instanceA_key, instanceA_tag_filter, 'A')
if not instanceB_tag_filter_id and instanceB_tag_filter:

Loading…
Cancel
Save