aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorParker <contact@pkrm.dev>2024-03-22 22:09:55 -0500
committerParker <contact@pkrm.dev>2024-03-22 22:09:55 -0500
commit237aec245e2a135b848dfd3c8dcf46cb755f08e9 (patch)
tree743fab39fa561139de64a9784078c1e00d85ee43 /app
parentbdc5d1fece0b3ee2ac8805ccee07ef93787eeb3e (diff)
Large Overhaul - Jellyfin Temp Accounts
Temporary jellyfin accounts can now be made through messaging. Commands were moved out and into their own files and functions for organization.
Diffstat (limited to 'app')
-rw-r--r--app/commands/movie_show_response_newaccount.py72
-rw-r--r--app/commands/number_response_request.py59
-rw-r--r--app/commands/request.py49
-rw-r--r--app/commands/status.py76
-rw-r--r--app/create_message.py14
-rw-r--r--app/db_removal.py24
-rw-r--r--app/db_setup.py32
-rw-r--r--app/initialize_variables.py142
-rw-r--r--app/messagearr.py245
-rw-r--r--app/validate_config.py261
-rw-r--r--app/wsgi.py6
11 files changed, 676 insertions, 304 deletions
diff --git a/app/commands/movie_show_response_newaccount.py b/app/commands/movie_show_response_newaccount.py
new file mode 100644
index 0000000..6922560
--- /dev/null
+++ b/app/commands/movie_show_response_newaccount.py
@@ -0,0 +1,72 @@
+import datetime
+import requests
+import random
+import string
+import sqlite3
+
+import initialize_variables
+from create_message import create_message
+
+
+def movie_show_response_newaccount(from_number, message):
+ if from_number not in initialize_variables.temp_new_account_requests.keys():
+ create_message(from_number, "There is no current request that you can decide on. It might be that your /newaccount command timed out due since you took too long to response. Please try again. If this issue persists, please contact Parker.")
+ return
+
+ # If its been 5 minutes since prompt was sent, alert user of timed out request
+ if (datetime.datetime.now() - initialize_variables.temp_new_account_requests[from_number]).total_seconds() / 60 > 5:
+ del initialize_variables.temp_new_account_requests[from_number]
+ create_message(from_number, "You waited too long and therefore your request has timed out.\n\nPlease try again by re-running the /newaccount command. If this issue persists, please contact Parker.")
+ return
+
+ if message.strip().lower() == "show":
+ active_time = 24
+
+ elif message.strip().lower() == "movie":
+ active_time = 4
+
+ else:
+ create_message(from_number, "You did not enter a valid response. Please re-send the /newaccount command and try again. If you believe this is an error, please contact Parker.")
+ return
+
+ # Otherwise, all checks have been completed
+ username = ''.join(random.choices(string.ascii_lowercase + string.digits, k=5))
+ password = ''.join(random.choices(string.ascii_lowercase + string.digits, k=15))
+
+ deletion_time = datetime.datetime.now() + datetime.timedelta(hours=active_time)
+ # Create new Jellyfin account
+ request_1 = requests.post(f'{initialize_variables.jellyfin_url}/Users/New', headers=initialize_variables.jellyfin_headers, json={'Name': username, 'Password': password})
+ if request_1.status_code != 200:
+ create_message(from_number, "Error creating Jellyfin account. Please try again. If the error persists, contact Parker.")
+ return
+
+ user_id = request_1.json()['Id']
+ # Get account policy and make edits
+ request_2 = requests.get(f'{initialize_variables.jellyfin_url}/Users/{user_id}', headers=initialize_variables.jellyfin_headers)
+ if request_2.status_code != 200:
+ create_message(from_number, "Error creating Jellyfin account. Please try again. If the error persists, contact Parker.")
+ return
+
+ policy = request_2.json()['Policy']
+ policy['SyncPlayAccess'] = 'JoinGroups'
+ policy['EnableContentDownloading'] = False
+ policy['InvalidLoginAttemptCount'] = 3
+ policy['MaxActiveSessions'] = 1
+ # Update user with new policy
+ request_3 = requests.post(f'{initialize_variables.jellyfin_url}/Users/{user_id}/Policy', headers=initialize_variables.jellyfin_headers, json=policy)
+ if request_3.status_code != 204:
+ create_message(from_number, "Error creating Jellyfin account. Please try again. If the error persists, contact Parker.")
+ return
+
+ # Add information to the database
+ db = sqlite3.connect(initialize_variables.db_path)
+ cursor = db.cursor()
+ cursor.execute('''
+ INSERT INTO jellyfin_accounts (user_id, deletion_time)
+ VALUES(?, ?)
+ ''', (user_id, deletion_time))
+ db.commit()
+ db.close()
+
+ create_message(from_number, f"Username: {username}\nPassword: {password}\n\nYour account will expire in {active_time} hours.")
+ return
diff --git a/app/commands/number_response_request.py b/app/commands/number_response_request.py
new file mode 100644
index 0000000..bb9958c
--- /dev/null
+++ b/app/commands/number_response_request.py
@@ -0,0 +1,59 @@
+import datetime
+import requests
+import sqlite3
+
+import initialize_variables
+from create_message import create_message
+
+
+def number_response_request(from_number, message):
+ if from_number not in initialize_variables.temp_movie_ids.keys():
+ create_message(from_number, "There is no current request that you can decide on. It might be that your /request command timed out due since you took too long to response. Please try again. If this issue persists, please contact Parker.")
+ return
+
+ # If its been 5 minutes since prompt was sent, alert user of timed out request
+ if (datetime.datetime.now() - initialize_variables.temp_movie_ids[from_number]['time']).total_seconds() / 60 > 5:
+ del initialize_variables.temp_movie_ids[from_number]
+ create_message(from_number, "You waited too long and therefore your request has timed out.\n\nPlease try again by re-running the /request command. If this issue persists, please contact Parker.")
+ return
+
+ # Otherwise, all checks have been completed
+ create_message(from_number, "Just a moment while I add your movie to the library...")
+ movie_number = initialize_variables.numbers_responses[message.strip()]
+ try:
+ tmdb_id = initialize_variables.temp_movie_ids[from_number]['ids'][movie_number - 1]
+ except IndexError:
+ create_message(from_number, "You did not enter a valid number. Please re-send the /request command and try again. If you believe this is an error, please contact Parker.")
+ del initialize_variables.temp_movie_ids[from_number]
+ return
+
+ data = requests.get(f'{initialize_variables.radarr_host_url}/api/v3/movie/lookup/tmdb?tmdbId={tmdb_id}', headers=initialize_variables.headers)
+
+ data = data.json()
+ movie_title = data['title']
+ # Change the qualityProfileId, monitored, and rootFolderPath values
+ data['qualityProfileId'] = initialize_variables.quality_profile_id
+ data['monitored'] = True
+ data['rootFolderPath'] = initialize_variables.root_folder_path
+ # Send data to Radarr API
+ response = requests.post(f'{initialize_variables.radarr_host_url}/api/v3/movie', headers=initialize_variables.headers, json=data)
+ data = response.json()
+ movie_id = data['id']
+ # Send message to user alerting them that the movie was added to the library
+ create_message(from_number, f"🎉 {data['title']} has been added to the library!\n\nTo check up on the status of your movie(s) send /status - please wait at least 5 minutes before running this command in order to get an accurate time.")
+
+ # After everything is completed, send Radarr a request to search indexers for new movie
+ requests.post(f'{initialize_variables.radarr_host_url}/api/v3/command', headers=initialize_variables.headers, json={'name': 'MoviesSearch', 'movieIds': [int(movie_id)]})
+
+ # Add the movie_id to the database so that users can check up on the status of their movie
+ db = sqlite3.connect(initialize_variables.db_path)
+ cursor = db.cursor()
+ cursor.execute('''
+ INSERT INTO movies(from_number, movie_id, movie_title)
+ VALUES(?, ?, ?)
+ ''', (from_number, movie_id, movie_title))
+ db.commit()
+ db.close()
+
+ del initialize_variables.temp_movie_ids[from_number]
+ return \ No newline at end of file
diff --git a/app/commands/request.py b/app/commands/request.py
new file mode 100644
index 0000000..316bd70
--- /dev/null
+++ b/app/commands/request.py
@@ -0,0 +1,49 @@
+import requests
+import datetime
+
+import initialize_variables
+from create_message import create_message
+
+
+def request(from_number, message):
+ # If the user has already run the /request command, delete the entry
+ # from the temp_movie_ids dict so that they can run the command again
+ if from_number in initialize_variables.temp_movie_ids.keys():
+ del initialize_variables.temp_movie_ids[from_number]
+
+ # If the user did not include a movie title, alert them to do so
+ if len(message) <= 9:
+ create_message(from_number, "Please include the movie title after the /request command.\nEX: /request The Dark Knight")
+ return
+
+ incoming_message = message.split(' ', 1)[1]
+ movie_request = incoming_message.replace(' ', '%20')
+ if movie_request.endswith("%20"):
+ movie_request = movie_request[:-3]
+
+ # Send a request to the radarr API to get the movie info
+ response = requests.get(f'{initialize_variables.radarr_host_url}/api/v3/movie/lookup?term={movie_request}', headers=initialize_variables.headers)
+
+ if len(response.json()) == 0:
+ create_message(from_number, "There were no results for that movie. Please make sure you typed the title correctly.")
+ return
+ # If the movie is already added to the library, return a message saying so.
+ if response.json()[0]['added'] != '0001-01-01T05:51:00Z':
+ create_message(from_number, "This movie is already added to the server.\n\nIf you believe this is an error, please contact Parker.")
+ return
+
+ # Add top 3 results to a message
+ message = ""
+ for i in range(min(3, len(response.json()))):
+ message += f"{i+1}. {response.json()[i]['folder']}\n\n"
+ if from_number not in initialize_variables.temp_movie_ids.keys():
+ initialize_variables.temp_movie_ids[from_number] = {
+ 'ids': [],
+ 'time': datetime.datetime.now()
+ }
+ initialize_variables.temp_movie_ids[from_number]['ids'].append(response.json()[i]['tmdbId'])
+
+ message += "Reply with the number associated with the movie you want to download. EX: 1\n\nIf the movie you want is not on the list, make sure you typed the title exactly as it is spelt, or ask Parker to manually add the movie."
+
+ create_message(from_number, message)
+ return \ No newline at end of file
diff --git a/app/commands/status.py b/app/commands/status.py
new file mode 100644
index 0000000..acf9376
--- /dev/null
+++ b/app/commands/status.py
@@ -0,0 +1,76 @@
+import datetime
+import sqlite3
+import requests
+import humanize
+
+import initialize_variables
+from create_message import create_message
+
+
+def status(from_number):
+ # This returns a list of ALL movies being downloaded, but not all of them were
+ # requested by the user, so we need to filter out the ones that were not requested
+ response = requests.get(f'{initialize_variables.radarr_host_url}/api/v3/queue/', headers=initialize_variables.headers)
+ # Get all the movie_ids that were requested by the user
+ db = sqlite3.connect(initialize_variables.db_path)
+ cursor = db.cursor()
+ cursor.execute('''
+ SELECT movie_id, movie_title FROM movies WHERE from_number = ?
+ ''', (from_number,))
+ movie_info = cursor.fetchall()
+ db.close()
+
+ movies = {} # movie_id: movie_title
+ for movie in movie_info:
+ movies[movie[0]] = movie[1]
+
+ if len(movies) == 0:
+ create_message(from_number, "You have no movies being downloaded at the moment.\n\nIf you previously added a movie, it is likely that it has finished downloading. If you believe this is an error, please contact Parker.")
+ return
+
+ message = ""
+ # Loop through the response from the radarr API and filter out the movies that were not requested by the user
+ for movie in response.json()['records']:
+ movie_id = str(movie['movieId'])
+ if movie_id in movies.keys():
+ if movie['status'] == 'downloading':
+ # Humanize the time_left value
+ try:
+ time_left = humanize.precisedelta(datetime.datetime.strptime(movie['timeleft'], '%H:%M:%S') - datetime.datetime.strptime('00:00:00', '%H:%M:%S'), minimum_unit='seconds')
+ except ValueError:
+ # Sometimes movie downloads take a long time and include days in the time_left value
+ # This is formated as 1.00:00:00
+ time_left = humanize.precisedelta(datetime.datetime.strptime(movie['timeleft'], '%d.%H:%M:%S') - datetime.datetime.strptime('00:00:00', '%H:%M:%S'), minimum_unit='seconds')
+ except KeyError:
+ time_left = 'Unknown'
+
+ message += f"📥 {movies[movie_id]} - {time_left}\n"
+ else:
+ message += f"{movies[movie_id]} - {str(movie['status']).upper()}\n"
+
+ # If the message is empty, that means the user has no movies being downloaded
+ # Or, no download was found for the movie they requested
+ if message == "":
+ # For all movie IDs within the database
+ for movie_id in movies.keys():
+ response = requests.get(f'{initialize_variables.radarr_host_url}/api/v3/movie/{movie_id}', headers=initialize_variables.headers)
+ # This means that there is no current download, and no file has been found
+ # MOST likely means a download just wasn't found, so alert the user
+ data = response.json()
+ if data['hasFile'] == False:
+ message += f"{movies[movie_id]} - NOT FOUND\n\nThis means a download was not found for the movie(s), if this is a brand new movie that is likely the reason. If the movie has already been released on DVD/Blu-Ray, please contact Parker."
+
+ # Send message with info about download to user, otherwise, the user has
+ # no movies being downloaded at the moment so alert them
+ if message != "":
+ create_message(from_number, message)
+ return
+ else:
+ create_message(from_number, "You have no movies being downloaded at the moment.\n\nIf you previously added a movie, it is likely that it has finished downloading. If you believe this is an error, please contact Parker.")
+ return
+
+ # Otherwise, add another part to the message containing movie data
+ else:
+ message += "\n\nIf movies consistently show as 'WARNING' or 'QUEUED' or any other error over multiple hours, please contact Parker."
+ create_message(from_number, message)
+ return \ No newline at end of file
diff --git a/app/create_message.py b/app/create_message.py
index f51c867..48097d5 100644
--- a/app/create_message.py
+++ b/app/create_message.py
@@ -1,21 +1,21 @@
import telnyx
from twilio.rest import Client
-from initialize_variables import *
+import initialize_variables
def create_message(number, message):
- if sms_service == 'telnyx':
- telnyx.api_key = telnyx_api_key
+ if initialize_variables.sms_service == 'telnyx':
+ telnyx.api_key = initialize_variables.telnyx_api_key
telnyx.Message.create(
- from_=api_number,
+ from_=initialize_variables.api_number,
to=number,
text=message
)
- if sms_service == 'twilio':
- client = Client(twilio_account_sid, twilio_auth_token)
+ if initialize_variables.sms_service == 'twilio':
+ client = Client(initialize_variables.twilio_account_sid, initialize_variables.twilio_auth_token)
client.messages.create(
body=message,
- from_=api_number,
+ from_=initialize_variables.api_number,
to=number
)
diff --git a/app/db_removal.py b/app/db_removal.py
index 1c49dd5..e9f6594 100644
--- a/app/db_removal.py
+++ b/app/db_removal.py
@@ -1,15 +1,16 @@
from apscheduler.schedulers.background import BackgroundScheduler
import sqlite3
import requests
+import datetime
-from initialize_variables import radarr_host_url, headers
+import initialize_variables
# Remove all entries from the database of movies that have already finished downloading
# This helps to stop from entries building up in the database and slowing down everything
sched = BackgroundScheduler(daemon=True)
@sched.scheduled_job('cron', hour='0', minute='0')
def clear_database():
- db = sqlite3.connect('/data/movies.db')
+ db = sqlite3.connect(initialize_variables.db_path)
cursor = db.cursor()
# First get all of the movie ids in the database
cursor.execute('''
@@ -17,7 +18,7 @@ def clear_database():
''')
movie_ids = cursor.fetchall()
# Get all of the movie_ids that are currently downloading/queued and/or missing
- response = requests.get(f'{radarr_host_url}/api/v3/queue/', headers=headers)
+ response = requests.get(f'{initialize_variables.radarr_host_url}/api/v3/queue/', headers=initialize_variables.headers)
current_movie_ids = []
for movie in response.json()['records']:
current_movie_ids.append(str(movie['movieId']))
@@ -30,4 +31,21 @@ def clear_database():
DELETE FROM movies WHERE movie_id = ?
''', (movie_id[0],))
db.commit()
+ db.close()
+
+@sched.scheduled_job('interval', seconds=10)
+def clear_jellyfin_accounts():
+ db = sqlite3.connect(initialize_variables.db_path)
+ cursor = db.cursor()
+ cursor.execute('''
+ SELECT user_id, deletion_time FROM jellyfin_accounts
+ ''')
+ data = cursor.fetchall()
+ for user_id, deletion_time in data:
+ if datetime.datetime.now() > datetime.datetime.strptime(deletion_time, '%Y-%m-%d %H:%M:%S.%f'):
+ requests.delete(f'{initialize_variables.jellyfin_url}/Users/{user_id}', headers=initialize_variables.jellyfin_headers)
+ cursor.execute('''
+ DELETE FROM jellyfin_accounts WHERE user_id = ?
+ ''', (user_id,))
+ db.commit()
db.close() \ No newline at end of file
diff --git a/app/db_setup.py b/app/db_setup.py
new file mode 100644
index 0000000..702449b
--- /dev/null
+++ b/app/db_setup.py
@@ -0,0 +1,32 @@
+import os
+import sqlite3
+import initialize_variables
+
+"""
+This function is run before the application starts - creates database and sets connection string
+"""
+def setup_db():
+ IN_DOCKER = os.environ.get('IN_DOCKER', False)
+ if IN_DOCKER:
+ db = sqlite3.connect('/data/movies.db')
+ initialize_variables.db_path = '/data/movies.db'
+ else:
+ db = sqlite3.connect('movies.db')
+ initialize_variables.db_path = 'movies.db'
+
+ cursor = db.cursor()
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS movies(
+ from_number TEXT,
+ movie_id TEXT,
+ movie_title TEXT
+ )
+ ''')
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS jellyfin_accounts(
+ user_id TEXT,
+ deletion_time DATETIME
+ )
+ ''')
+ db.commit()
+ db.close()
diff --git a/app/initialize_variables.py b/app/initialize_variables.py
index 9dfda1a..09221f7 100644
--- a/app/initialize_variables.py
+++ b/app/initialize_variables.py
@@ -1,93 +1,61 @@
-import os
-import yaml
-import requests
-
supported_sms_services = ['telnyx', 'twilio']
-radarr_host_url = str(os.environ['RADARR_HOST_URL'])
-radarr_api_key = str(os.environ['RADARR_API_KEY'])
-enable_kuma_notifications = str(os.environ['ENABLE_KUMA_NOTIFICATIONS']).lower()
-sms_service = str(os.environ['SMS_SERVICE']).lower()
-
-headers = {
- 'Content-Type': 'application/json',
- 'X-Api-Key': radarr_api_key
-}
-
-# Open the config.yaml file and see if the config is set
-try:
- with open('/data/config.yaml', 'r') as f:
- file = yaml.load(f, Loader=yaml.FullLoader)
- try:
- quality_profile_id = int(file['quality_profile_id'])
-
- if str(file['home_domain']) != 'null':
- home_domain = str(file['home_domain'])
-
- api_number = str(file['api_number'])
- val_nums = str(file['valid_senders'])
- root_folder_path = str(file['root_folder_path'])
-
- if enable_kuma_notifications == 'true':
- notif_receivers_nums = str(file['notif_receivers'])
- authorization_header_token = str(file['authorization_header_token'])
-
- if sms_service not in supported_sms_services:
- print(f'{sms_service} is not a supported SMS service. Please choose from the supported list: {supported_sms_services}')
- exit()
-
- if sms_service == 'telnyx':
- telnyx_api_key = str(file['telnyx_api_key'])
-
- if sms_service == 'twilio':
- twilio_account_sid = str(file['twilio_account_sid'])
- twilio_auth_token = str(file['twilio_auth_token'])
-
- value_not_set = False
- except:
- print('One or more values are not set or not set correctly within the config.yaml file. Please edit the file or refer to the docs for more information.')
- exit()
-
-except FileNotFoundError:
- # Create the config.yaml file
- with open('/data/config.yaml', 'w') as f:
- value_not_set = True
-
-if value_not_set:
- print('One or more values are not set or not set correctly within the config.yaml file. Please edit the file or refer to the docs for more information.')
- data = requests.get(f'{radarr_host_url}/api/v3/qualityprofile', headers=headers).json()
- # Open config.yaml and write each profile as a comment to the file
- with open('/data/config.yaml', 'w') as f:
- f.write('# Quality Profile ID\'s\n')
- for entry in data:
- f.write(f'# {entry["id"]} - {entry["name"]}\n')
-
- f.write("quality_profile_id:\n")
- f.write("home_domain: null\n")
- f.write("api_number: ''\n")
- f.write("valid_senders: ''\n")
- f.write("root_folder_path:\n")
-
- if enable_kuma_notifications == 'true':
- f.write("notif_receivers: ''\n")
- f.write("authorization_header_token: uptimekumaauthtoken\n")
-
- if sms_service not in supported_sms_services:
- print(f'{sms_service} is not a supported SMS service. Please choose from the supported list: {supported_sms_services}')
- exit()
-
- if sms_service == 'telnyx':
- f.write("telnyx_api_key:\n")
-
- if sms_service == 'twilio':
- f.write("twilio_account_sid:\n")
- f.write("twilio_auth_token:\n")
-
- f.write("\n\n# INFORMATION: There should be NO trailing spaced after you enter a value,\n# this will cause errors.\n# There should be one space after the colon though (e.g. quality_profile_id: 1)\n# Check docs for information on each value.")
- exit()
-
numbers_responses = {
'1': 1, 'one': 1, '1.': 1,
'2': 2, 'two': 2, '2.': 2,
'3': 3, 'three': 3, '3.': 3
-} \ No newline at end of file
+}
+
+def init():
+ global sms_service
+ sms_service = ''
+ global telnyx_api_key
+ telnyx_api_key = ''
+ global twilio_account_sid
+ twilio_account_sid = ''
+ global twilio_auth_token
+ twilio_auth_token = ''
+ global api_number
+ api_number = ''
+ global valid_senders
+ valid_senders = []
+ global radarr_host_url
+ radarr_host_url = ''
+ global headers
+ headers = ''
+ global root_folder_path
+ root_folder_path = ''
+ global quality_profile_id
+ quality_profile_id = ''
+ global authorization_header_tokens
+ authorization_header_tokens= ''
+ global notifs_recievers
+ notifs_recievers = []
+ global enable_jellyfin_temp_accounts
+ enable_jellyfin_temp_accounts = ''
+ global jellyfin_url
+ jellyfin_url = ''
+ global jellyfin_headers
+ jellyfin_headers = ''
+ global home_domain
+ home_domain = ''
+ global db_path
+ db_path = ''
+
+ global temp_movie_ids
+ temp_movie_ids = {}
+ """
+ {
+ 'from_number': {
+ 'ids': ['tmdb_id_one', 'tmdb_id_two', 'tmdb_id_three'],
+ 'time': 'time of request'
+ }
+ }
+ """
+ global temp_new_account_requests
+ temp_new_account_requests = {}
+ """
+ {
+ 'from_number': 'time'
+ }
+ """ \ No newline at end of file
diff --git a/app/messagearr.py b/app/messagearr.py
index 6f437c7..8e6b8e4 100644
--- a/app/messagearr.py
+++ b/app/messagearr.py
@@ -1,50 +1,15 @@
import flask
import datetime
-import requests
-import sqlite3
-import humanize
from create_message import create_message
-from initialize_variables import *
+from commands.request import request
+from commands.status import status
+from commands.number_response_request import number_response_request
+from commands.movie_show_response_newaccount import movie_show_response_newaccount
+import initialize_variables
-
-"""
-Define variables to be used later on
-"""
app = flask.Flask(__name__)
-db = sqlite3.connect('/data/movies.db')
-cursor = db.cursor()
-cursor.execute('''
- CREATE TABLE IF NOT EXISTS movies(
- from_number TEXT,
- movie_id TEXT,
- movie_title TEXT
- )
-''')
-db.commit()
-db.close()
-
-temp_movie_ids = {}
-"""
-{
- 'from_number': {
- 'ids': ['tmdb_id_one', 'tmdb_id_two', 'tmdb_id_three'],
- 'time': 'time of request'
- }
-}
-"""
-valid_senders = []
-
-for number in val_nums.split(', '):
- valid_senders.append(number)
-
-if notif_receivers_nums:
- notif_receivers = []
-
- for number in notif_receivers_nums.split(', '):
- notif_receivers.append(number)
-
"""
POST request route to accept incoming notifications from UptimeKuma
@@ -52,9 +17,9 @@ regarding the status of certain services. Messages are sent to the
'notif_receivers' list whenever a service goes down or comes back up.
"""
@app.route('/kuma', methods=['POST'])
-def api():
+def kuma():
# Make sure the request is coming from UptimeKuma (Configured to use this authorization token)
- if flask.request.headers.get('Authorization') == authorization_header_token:
+ if flask.request.headers.get('Authorization') == initialize_variables.authorization_header_tokens:
data = flask.request.get_json()
if data['heartbeat']['status'] == 0:
@@ -63,7 +28,7 @@ def api():
elif data['heartbeat']['status'] == 1:
message = f"✅ {data['monitor']['name']} is up!"
- for number in notif_receivers:
+ for number in initialize_variables.notifs_recievers:
create_message(number, message)
return 'OK'
@@ -80,183 +45,49 @@ and then run the command if it is valid.
@app.route('/incoming', methods=['POST'])
def incoming():
# Get the data and define the from_number (number that sent the message)
- if sms_service == 'telnyx':
+ if initialize_variables.sms_service == 'telnyx':
from_number = flask.request.get_json()['data']['payload']['from']['phone_number']
message = str(flask.request.get_json()['data']['payload']['text'])
- if sms_service == 'twilio':
+ if initialize_variables.sms_service == 'twilio':
from_number = flask.request.form['From']
message = str(flask.request.form['Body'])
# Make sure the number is a valid_sender, this stops random people from
# adding movies to the library
- if from_number not in valid_senders:
+ if from_number not in initialize_variables.valid_senders:
return 'OK'
- # If the message starts with /request, that means the user is trying to add a movie
- if message.startswith('/request'):
- # If the user has already run the /request command, delete the entry
- # from the temp_movie_ids dict so that they can run the command again
- if from_number in temp_movie_ids.keys():
- del temp_movie_ids[from_number]
- # If the user did not include a movie title, alert them to do so
- # Just check to make sure that the length of the message is greater than 9
- if len(message) <= 9:
- create_message(from_number, "Please include the movie title after the /request command.\nEX: /request The Dark Knight")
- return 'OK'
- incoming_message = message.split(' ', 1)[1]
- movie_request = incoming_message.replace(' ', '%20')
- # Send a request to the radarr API to get the movie info
- response = requests.get(f'{radarr_host_url}/api/v3/movie/lookup?term={movie_request}', headers=headers)
- # If there are no results, alert the user
- if len(response.json()) == 0:
- create_message(from_number, "There were no results for that movie. Please make sure you typed the title correctly.")
- return 'OK'
- # If the movie is already added to the library, return a message saying so.
- if response.json()[0]['added'] != '0001-01-01T05:51:00Z':
- create_message(from_number, "This movie is already added to the server.\n\nIf you believe this is an error, please contact Parker.")
- return 'OK'
- # Define an empty message variable, we then loop through the first 3 results from the API
- # If there are less than 3 results, we loop through the amount of results there are
- message = ""
- for i in range(min(3, len(response.json()))):
- message += f"{i+1}. {response.json()[i]['folder']}\n\n"
- if from_number not in temp_movie_ids.keys():
- temp_movie_ids[from_number] = {
- 'ids': [],
- 'time': datetime.datetime.now()
- }
- temp_movie_ids[from_number]['ids'].append(response.json()[i]['tmdbId'])
-
- message += "Reply with the number associated with the movie you want to download. EX: 1\n\nIf the movie you want is not on the list, make sure you typed the title exactly as it is spelt, or ask Parker to manually add the movie."
-
- create_message(from_number, message)
+ if message.startswith('/request'):
+ request(from_number, message)
return 'OK'
- # Elif the user responded with a variation of 1, 2, or 3
- # This means they are replying to the previous prompt, so now we need to
- # add their movie choice to radarr for download
- elif message.strip() in numbers_responses.keys():
- # If there is no entry for the user in the temp_movie_ids dict, that means
- # they have not yet run the /request command, so alert them to do so.
- if from_number not in temp_movie_ids.keys():
- create_message(from_number, "There is no current request that you can decide on. It might be that your /request command timed out due since you took too long to response. Please try again. If this issue persists, please contact Parker.")
- return 'OK'
- # If the time is greater than 5 minutes, delete the entry from the dict, and alert
- # the user that their request timed out
- if (datetime.datetime.now() - temp_movie_ids[from_number]['time']).total_seconds() / 60 > 5:
- del temp_movie_ids[from_number]
- create_message(from_number, "You waited too long and therefore your request has timed out.\n\nPlease try again by re-running the /request command. If this issue persists, please contact Parker.")
- return 'OK'
-
- # Otherwise, all checks have been completed, so alert the user of the
- # start of the process
- create_message(from_number, "Just a moment while I add your movie to the library...")
- movie_number = numbers_responses[message.strip()]
- try:
- tmdb_id = temp_movie_ids[from_number]['ids'][movie_number - 1]
- except IndexError:
- create_message(from_number, "You did not enter a valid number. Please re-send the /request command and try again. If you believe this is an error, please contact Parker.")
- del temp_movie_ids[from_number]
- return 'OK'
-
- data = requests.get(f'{radarr_host_url}/api/v3/movie/lookup/tmdb?tmdbId={tmdb_id}', headers=headers)
-
- data = data.json()
- movie_title = data['title']
- # Change the qualityProfileId, monitored, and rootFolderPath values
- data['qualityProfileId'] = quality_profile_id
- data['monitored'] = True
- data['rootFolderPath'] = root_folder_path
- # Pass this data into a pass request to the radarr API, this will add the movie to the library
- response = requests.post(f'{radarr_host_url}/api/v3/movie', headers=headers, json=data)
- data = response.json()
- movie_id = data['id']
- # Send message to user alerting them that the movie was added to the library
- create_message(from_number, f"🎉 {data['title']} has been added to the library!\n\nTo check up on the status of your movie(s) send /status - please wait at least 5 minutes before running this command in order to get an accurate time.")
- # Finally, as to not slow up the sending of the message, send this request
- # Send a POST request to the radarr API to search for the movie in the indexers
- requests.post(f'{radarr_host_url}/api/v3/command', headers=headers, json={'name': 'MoviesSearch', 'movieIds': [int(movie_id)]})
- # Add the movie_id to the database so that users can check up on the status of their movie
- db = sqlite3.connect('/data/movies.db')
- cursor = db.cursor()
- cursor.execute('''
- INSERT INTO movies(from_number, movie_id, movie_title)
- VALUES(?, ?, ?)
- ''', (from_number, movie_id, movie_title))
- db.commit()
- db.close()
-
- # Delete the entry from the temp_movie_ids dict
- del temp_movie_ids[from_number]
+ # If a user responded with a number, they are responding to
+ # the 'request' command prompt
+ elif message.strip() in initialize_variables.numbers_responses.keys():
+ number_response_request(from_number, message)
return 'OK'
- elif message.strip() == '/status':
- # This returns a list of ALL movies being downloaded, but not all of them were
- # requested by the user, so we need to filter out the ones that were not requested
- response = requests.get(f'{radarr_host_url}/api/v3/queue/', headers=headers)
- # Get all the movie_ids that were requested by the user
- db = sqlite3.connect('/data/movies.db')
- cursor = db.cursor()
- cursor.execute('''
- SELECT movie_id, movie_title FROM movies WHERE from_number = ?
- ''', (from_number,))
- movie_info = cursor.fetchall()
- db.close()
- # Turn the movie_id, movie_title into key value pairs
- movies = {}
- for movie in movie_info:
- movies[movie[0]] = movie[1]
-
- # If the user has no movies in the database, alert them to run the /request command
- if len(movies) == 0:
- create_message(from_number, "You have no movies being downloaded at the moment.\n\nIf you previously added a movie, it is likely that it has finished downloading. If you believe this is an error, please contact Parker.")
- return 'OK'
+ elif message.startswith('/status'):
+ status(from_number)
+ return 'OK'
- message = ""
- # Loop through the response from the radarr API and filter out the movies that were not requested by the user
- for movie in response.json()['records']:
- movie_id = str(movie['movieId'])
- if movie_id in movies.keys():
- if movie['status'] == 'downloading':
- # Humanize the time_left value
- try:
- time_left = humanize.precisedelta(datetime.datetime.strptime(movie['timeleft'], '%H:%M:%S') - datetime.datetime.strptime('00:00:00', '%H:%M:%S'), minimum_unit='seconds')
- except ValueError:
- # Sometimes movie downloads take a long time and include days in the time_left value
- # This is formated as 1.00:00:00
- time_left = humanize.precisedelta(datetime.datetime.strptime(movie['timeleft'], '%d.%H:%M:%S') - datetime.datetime.strptime('00:00:00', '%H:%M:%S'), minimum_unit='seconds')
- except KeyError:
- time_left = 'Unknown'
+ elif message.startswith('/newaccount'):
+ if initialize_variables.enable_jellyfin_temp_accounts.lower() == 'true':
+ # If number is already in the temp dict, delete it so that they can redo the request
+ if from_number in initialize_variables.temp_new_account_requests.keys():
+ del initialize_variables.temp_new_account_requests[from_number]
- message += f"📥 {movies[movie_id]} - {time_left}\n"
- else:
- message += f"{movies[movie_id]} - {str(movie['status']).upper()}\n"
+ create_message(from_number, "Will you be watching a TV show or a movie?\n\nRespond with 'show' for TV show, 'movie' for movies")
+ initialize_variables.temp_new_account_requests[from_number] = datetime.datetime.now()
+ return 'OK'
- # If the message is empty, that means the user has no movies being downloaded
- # Or, no download was found for the movie they requested
- if message == "":
- # For all movie IDs within the database
- for movie_id in movies.keys():
- response = requests.get(f'{radarr_host_url}/api/v3/movie/{movie_id}', headers=headers)
- # This means that there is no current download, and no file has been found
- # MOST likely means a download just wasn't found, so alert the user
- data = response.json()
- if data['hasFile'] == False:
- message += f"{movies[movie_id]} - NOT FOUND\n\nThis means a download was not found for the movie(s), if this is a brand new movie that is likely the reason. If the movie has already been released on DVD/Blu-Ray, please contact Parker."
+ # User must be responding to above prompt
+ elif message.strip().lower() in ['show', 'movie']:
+ if initialize_variables.enable_jellyfin_temp_accounts.lower() == 'true':
+ movie_show_response_newaccount(from_number, message)
+ return 'OK'
- # If the message is still empty, that means the user has no movies being downloaded
- if message != "":
- create_message(from_number, message)
- return 'OK'
- else:
- create_message(from_number, "You have no movies being downloaded at the moment.\n\nIf you previously added a movie, it is likely that it has finished downloading. If you believe this is an error, please contact Parker.")
- return 'OK'
- # Otherwise, add another part to the message containing movie data
- else:
- message += "\n\nIf movies consistently show as 'WARNING' or 'QUEUED' or any other error over multiple hours, please contact Parker."
- create_message(from_number, message)
- return 'OK'
# No valid commands were found, so just return
else:
return 'OK'
@@ -265,12 +96,12 @@ def incoming():
# Handle 405 errors - when a user attempts a GET request on a POST only route
@app.errorhandler(405)
def method_not_allowed(e):
- if home_domain != 'None':
- return flask.redirect(home_domain)
+ if initialize_variables.home_domain != 'None':
+ return flask.redirect(initialize_variables.home_domain)
return 'Method Not Allowed'
@app.errorhandler(404)
def page_not_found(e):
- if home_domain != 'None':
- return flask.redirect(home_domain)
- return 'Page Not Found'
+ if initialize_variables.home_domain != 'None':
+ return flask.redirect(initialize_variables.home_domain)
+ return 'Page Not Found' \ No newline at end of file
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
diff --git a/app/wsgi.py b/app/wsgi.py
index d3cd6c6..9b73735 100644
--- a/app/wsgi.py
+++ b/app/wsgi.py
@@ -5,8 +5,14 @@ import multiprocessing
import asyncio
from db_removal import sched
+import initialize_variables
+import validate_config
+import db_setup
if __name__ == '__main__':
+ initialize_variables.init()
+ db_setup.setup_db()
+ validate_config.make_config()
multiprocessing.Process(target=sched.start()).start()
print('Starting server...')
config = Config()