aboutsummaryrefslogtreecommitdiff
path: root/app/validate_config.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/validate_config.py')
-rw-r--r--app/validate_config.py261
1 files changed, 261 insertions, 0 deletions
diff --git a/app/validate_config.py b/app/validate_config.py
new file mode 100644
index 0000000..8cad0f5
--- /dev/null
+++ b/app/validate_config.py
@@ -0,0 +1,261 @@
+import configparser
+import os
+from simple_chalk import chalk
+import validators
+import requests
+import initialize_variables
+
+def write_to_config(config):
+ IN_DOCKER = os.environ.get('IN_DOCKER', False)
+ if IN_DOCKER:
+ with open('/data/config.ini', 'w') as configfile:
+ config.write(configfile)
+ else:
+ with open('config.ini', 'w') as configfile:
+ config.write(configfile)
+
+
+def validate_config(file_contents):
+ config = configparser.ConfigParser()
+ config.read_string(file_contents)
+
+ # Check SMS service
+ if config['REQUIRED']['SMS_SERVICE'].lower() not in initialize_variables.supported_sms_services:
+ print(chalk.red(f'Invalid or empty SMS_SERVICE option passed. Please choose from the supported list: {initialize_variables.supported_sms_services}'))
+ exit()
+ initialize_variables.sms_service = config['REQUIRED']['SMS_SERVICE'].lower()
+
+ # Check API key is Telnyx is selected
+ if config['REQUIRED']['SMS_SERVICE'].lower() == 'telnyx':
+ try:
+ if not config['REQUIRED']['TELNYX_API_KEY']:
+ print(chalk.red('Empty TELNYX_API_KEY option passed. Please enter the API key for your Telnyx account.'))
+ exit()
+ except KeyError:
+ config['REQUIRED']['TELNYX_API_KEY'] = ''
+ write_to_config(config)
+ print(chalk.red('Empty TELNYX_API_KEY option passed. Please enter the API key for your Telnyx account.'))
+ initialize_variables.telnyx_api_key = config['REQUIRED']['TELNYX_API_KEY']
+
+ # Check account SID and auth token is Twilio is selected
+ if config['REQUIRED']['SMS_SERVICE'].lower() == 'twilio':
+ try:
+ if not config['REQUIRED']['TWILIO_ACCOUNT_SID'] or not config['REQUIRED']['TWILIO_AUTH_TOKEN']:
+ print(chalk.red('Empty TWILIO_ACCOUNT_SID or TWILIO_AUTH_TOKEN option passed. Please enter the account SID and auth token for your Twilio account.'))
+ exit()
+ except KeyError:
+ config['REQUIRED']['TWILIO_ACCOUNT_SID'] = ''
+ config['REQUIRED']['TWILIO_AUTH_TOKEN'] = ''
+ write_to_config(config)
+ print(chalk.red('Empty TWILIO_ACCOUNT_SID or TWILIO_AUTH_TOKEN option passed. Please enter the account SID and auth token for your Twilio account.'))
+ initialize_variables.twilio_account_sid = config['REQUIRED']['TWILIO_ACCOUNT_SID']
+ initialize_variables.twilio_auth_token = config['REQUIRED']['TWILIO_AUTH_TOKEN']
+
+ # Check API_NUMBER
+ if not config['REQUIRED']['API_NUMBER']:
+ print(chalk.red('Empty API_NUMBER option passed. Please enter an internationally formatted phone number with no spaces.'))
+ exit()
+ if len(config['REQUIRED']['API_NUMBER']) < 12 or len(config['REQUIRED']['API_NUMBER']) > 13 or not config['REQUIRED']['API_NUMBER'].startswith('+'):
+ print(chalk.red('API_NUMBER must be a valid international phone number with no spaces (e.g. +15459087689)'))
+ exit()
+ initialize_variables.api_number = config['REQUIRED']['API_NUMBER']
+
+ # Check VALID_SENDERS
+ if not config['REQUIRED']['VALID_SENDERS']:
+ print(chalk.red('Empty VALID_SENDERS option passed. Please enter a command separated list of internationally formatted phone numbers (e.g. +15359087689, +15256573847)'))
+ exit()
+
+ for sender in config['REQUIRED']['VALID_SENDERS'].split(', '):
+ if len(sender) < 12 or len(sender) > 13 or not sender.startswith('+'):
+ print(chalk.red('At least one number within VALID_SENDER is malformed. Please enter a command separated list of internationally formatted phone numbers (e.g. +15359087689, +15256573847)'))
+ exit()
+ else:
+ initialize_variables.valid_senders.append(sender)
+
+ # Check RADARR_HOST_URL
+ if not validators.url(config['REQUIRED']['RADARR_HOST_URL']):
+ print(chalk.red('Invalid or empty URL passed to RADARR_HOST_URL. Pass a valid URL (e.g. http://localhost:7878)'))
+ exit()
+ initialize_variables.radarr_host_url = config['REQUIRED']['RADARR_HOST_URL']
+
+ # Check RADARR_API_KEY
+ if not config['REQUIRED']['RADARR_API_KEY']:
+ print(chalk.red('Empty RADARR_API_KEY passed. Obtain an API key from your Radarr instance and paste it in this option.'))
+ exit()
+
+ initialize_variables.headers = {
+ 'Content-Type': 'application/json',
+ 'X-Api-Key': config['REQUIRED']['RADARR_API_KEY']
+ }
+
+ # Make sure connection to Radarr API can be established
+ try:
+ requests.get(config['REQUIRED']['RADARR_HOST_URL'], headers=initialize_variables.headers)
+ except requests.exceptions.ConnectionError:
+ print(chalk.red('Could not connect to Radarr API. Please check your RADARR_HOST_URL and RADARR_API_KEY'))
+ exit()
+
+ # Check ROOT_FOLDER_PATH
+ if not config['REQUIRED']['ROOT_FOLDER_PATH']:
+ print(chalk.red('Empty ROOT_FOLDER_PATH option passed. Please enter a path to a folder within your Radarr instance.'))
+ exit()
+ initialize_variables.root_folder_path = config['REQUIRED']['ROOT_FOLDER_PATH']
+
+ # Check QUALITY_PROFILE_ID
+ data = requests.get(f'{config["REQUIRED"]["RADARR_HOST_URL"]}/api/v3/qualityprofile', headers=initialize_variables.headers).json()
+ all_ids = []
+ for entry in data:
+ all_ids.append(str(entry['id']))
+
+ if not config['REQUIRED']['QUALITY_PROFILE_ID'] or config['REQUIRED']['QUALITY_PROFILE_ID'] not in all_ids:
+ config['AVAILABLE_QUALITY_IDS'] = {}
+ for entry in data:
+ config['AVAILABLE_QUALITY_IDS'][str(entry['id'])] = entry['name']
+
+ print(chalk.red('Empty or invalid QUALITY_PROFILE_ID passed. Pass one of the valid IDs which are now listed within the config.ini file.'))
+ write_to_config(config)
+ exit()
+ initialize_variables.quality_profile_id = config['REQUIRED']['QUALITY_PROFILE_ID']
+
+ # Check ENABLE_KUMA_NOTIFICATIONS
+ if not config['REQUIRED']['ENABLE_KUMA_NOTIFICATIONS'] or config['REQUIRED']['ENABLE_KUMA_NOTIFICATIONS'].lower() not in ['true', 'false']:
+ print(chalk.red('ENABLE_KUMA_NOTIFICATIONS must be a boolean value (true/false)'))
+ exit()
+
+ if config['REQUIRED']['ENABLE_KUMA_NOTIFICATIONS'].lower() == 'true':
+ # Check existence
+ try:
+ if not config['KUMA_NOTIFICATIONS']['AUTHORIZATION_HEADER_TOKEN']:
+ print(chalk.red('Empty AUTHORIZATION_HEADER_TOKEN passed. Make sure to set your authorization header in Uptime Kuma and copy the key here.'))
+ exit()
+ except KeyError:
+ config['KUMA_NOTIFICATIONS']['AUTHORIZATION_HEADER_TOKEN'] = ''
+ write_to_config(config)
+ print(chalk.red('Empty AUTHORIZATION_HEADER_TOKEN passed. Make sure to set your authorization header in Uptime Kuma and copy the key here.'))
+ exit()
+ initialize_variables.authorization_header_tokens = config['KUMA_NOTIFICATIONS']['AUTHORIZATION_HEADER_TOKEN']
+ # Check existence
+ try:
+ if not config['KUMA_NOTIFICATIONS']['NOTIF_RECIEVERS']:
+ print(chalk.red('Empty NOTIF_RECIEVERS passed. This should be a comma separated list of the numbers of people who should recieve uptime notifications - formatted the same way as VALID_SENDERS.'))
+ exit()
+ except KeyError:
+ config['KUMA_NOTIFICATIONS']['NOTIF_RECIEVERS'] = ''
+ write_to_config(config)
+ print(chalk.red('Empty NOTIF_RECIEVERS passed. This should be a comma separated list of the numbers of people who should recieve uptime notifications - formatted the same way as VALID_SENDERS.'))
+ exit()
+
+ # Check validity of NOTIF_RECIEVERS
+ for sender in config['KUMA_NOTIFICATIONS']['NOTIF_RECIEVERS'].split(', '):
+ if len(sender) < 12 or len(sender) > 13 or not sender.startswith('+'):
+ print(chalk.red('At least one number within NOTIF_RECIEVERS is malformed. Please enter a command separated list of internationally formatted phone numbers (e.g. +15359087689, +15256573847)'))
+ exit()
+ else:
+ initialize_variables.notifs_recievers.append(sender)
+
+ # Check ENABLE_JELLYFIN_TEMP_ACCOUNTS
+ if not config['REQUIRED']['ENABLE_JELLYFIN_TEMP_ACCOUNTS'] or config['REQUIRED']['ENABLE_JELLYFIN_TEMP_ACCOUNTS'].lower() not in ['true', 'false']:
+ print(chalk.red('ENABLE_JELLYFIN_TEMP_ACCOUNTS must be a boolean value (true/false)'))
+ exit()
+ initialize_variables.enable_jellyfin_temp_accounts = config['REQUIRED']['ENABLE_JELLYFIN_TEMP_ACCOUNTS'].lower()
+
+ if config['REQUIRED']['ENABLE_JELLYFIN_TEMP_ACCOUNTS'].lower() == 'true':
+ # Check existence
+ try:
+ if not config['JELLYFIN_ACCOUNTS']['JELLYFIN_URL']:
+ print(chalk.red('Empty URL passed to JELLYFIN_URL. Pass a valid URL (e.g. http://localhost:8096)'))
+ exit()
+ except KeyError:
+ config['JELLYFIN_ACCOUNTS']['JELLYFIN_URL'] = ''
+ write_to_config(config)
+ print(chalk.red('Empty URL passed to JELLYFIN_URL. Pass a valid URL (e.g. http://localhost:8096)'))
+ exit()
+ # Check URL validity
+ if not validators.url(config['JELLYFIN_ACCOUNTS']['JELLYFIN_URL']):
+ print(chalk.red('Invalid URL passed to JELLYFIN_URL. Pass a valid URL (e.g. http://localhost:8096)'))
+ exit()
+ initialize_variables.jellyfin_url = config['JELLYFIN_ACCOUNTS']['JELLYFIN_URL']
+
+ # Check existence
+ try:
+ if not config['JELLYFIN_ACCOUNTS']['JELLYFIN_API_KEY']:
+ print(chalk.red('Empty JELLYFIN_API_KEY passed. Create a Jellyfin API key in your Jellyfin dashboard and pass it here.'))
+ exit()
+ except KeyError:
+ config['JELLYFIN_ACCOUNTS']['JELLYFIN_API_KEY'] = ''
+ write_to_config(config)
+ print(chalk.red('Empty JELLYFIN_API_KEY passed. Create a Jellyfin API key in your Jellyfin dashboard and pass it here.'))
+ exit()
+
+ # Make sure connection to Jellyfin API can be established
+ initialize_variables.jellyfin_headers = {
+ 'Content-Type': 'application/json',
+ 'Authorization': f"MediaBrowser Client=\"other\", device=\"Messagearr\", DeviceId=\"totally-unique-device-id\", Version=\"0.0.0\", Token=\"{config['JELLYFIN_ACCOUNTS']['JELLYFIN_API_KEY']}\""
+ }
+
+ response = requests.get(f"{config['JELLYFIN_ACCOUNTS']['JELLYFIN_URL']}/Users", headers=initialize_variables.jellyfin_headers)
+ if response.status_code != 200:
+ print(chalk.red('Could not connect to Jellyfin API. Please check your JELLYFIN_URL and JELLYFIN_API_KEY'))
+ exit()
+
+ # Validate home domain if it is set
+ if config['OPTIONAL']['HOME_DOMAIN']:
+ if not validators.url(config['OPTIONAL']['HOME_DOMAIN']):
+ print(chalk.red('Invalid HOME_DOMAIN passed. Please enter a valid url (e.g. https://example.com)'))
+ exit()
+ else:
+ initialize_variables.home_domain = config['OPTIONAL']['HOME_DOMAIN']
+
+"""
+This method is called before starting the application - to make and validate the configuration
+"""
+def make_config():
+ # Attempt to open and validate the configuration file
+ try:
+ with open('config.ini', 'r') as config:
+ file_contents = config.read()
+ validate_config(file_contents)
+
+ except FileNotFoundError:
+ try:
+ with open('/data/config.ini', 'r') as config:
+ file_contents = config.read()
+ validate_config(file_contents)
+
+ except FileNotFoundError:
+ # Create the config.ini file
+ config = configparser.ConfigParser()
+ config['REQUIRED'] = {
+ 'SMS_SERVICE': '',
+ 'API_NUMBER': '',
+ 'VALID_SENDERS': '',
+ 'RADARR_HOST_URL': 'http://',
+ 'RADARR_API_KEY': '',
+ 'ROOT_FOLDER_PATH': '',
+ 'QUALITY_PROFILE_ID': '',
+ 'ENABLE_KUMA_NOTIFICATIONS': '',
+ 'ENABLE_JELLYFIN_TEMP_ACCOUNTS': ''
+ }
+
+ config['OPTIONAL'] = {
+ 'HOME_DOMAIN': ''
+ }
+
+ config['KUMA_NOTIFICATIONS'] = {
+ 'AUTHORIZATION_HEADER_TOKEN': '',
+ 'NOTIF_RECIEVERS': ''
+ }
+
+ config['JELLYFIN_ACCOUNTS'] = {
+ 'JELLYFIN_URL': '',
+ 'JELLYFIN_API_KEY': ''
+ }
+
+ IN_DOCKER = os.environ.get('IN_DOCKER', False)
+ if IN_DOCKER:
+ with open('/data/config.ini', 'w') as configfile:
+ config.write(configfile)
+
+ else:
+ with open('config.ini', 'w') as configfile:
+ config.write(configfile) \ No newline at end of file