Compare commits

..

No commits in common. "main" and "1.4.14" have entirely different histories.
main ... 1.4.14

5 changed files with 58 additions and 121 deletions

View File

@ -1,5 +1,5 @@
[tool.bumpversion]
current_version = "1.4.19"
current_version = "1.4.14"
commit = true
tag = true
tag_name = "{new_version}"

View File

@ -1 +1 @@
1.4.19
1.4.14

90
app.py
View File

@ -260,10 +260,9 @@ def add_account() -> Union[Response, str]:
username = request.form["username"]
password = request.form["password"]
stream = request.form["stream"]
result = add_user_account(
if add_user_account(
base_url, session["auth_credentials"], username, password, stream
)
if result is True:
):
# Clear cache for user accounts route
cache_key = f"view/{session['username']}/accounts"
cache.delete(cache_key)
@ -273,18 +272,9 @@ def add_account() -> Union[Response, str]:
cache_key_home = f"view/{session['username']}/home"
cache.delete(cache_key_home)
# Run the NPM config update in a background thread
thread = threading.Thread(target=_update_npm_config_in_background, args=(session["auth_credentials"],))
thread = threading.Thread(target=_update_npm_config_in_background)
thread.start()
return redirect(url_for("user_accounts"))
elif result is False:
# Account already exists
error = "Account already exists for this user"
return render_template(
"add_account.html",
text_input_enabled=app.config.get("TEXT_INPUT_ENABLED"),
shared_text=shared_text,
error=error
)
return render_template(
"add_account.html",
@ -306,9 +296,6 @@ def delete_account() -> Response:
# Clear home page cache as well since it shows account stats
cache_key_home = f"view/{session['username']}/home"
cache.delete(cache_key_home)
# Run the NPM config update in a background thread to remove the deleted account's redirect
thread = threading.Thread(target=_update_npm_config_in_background, args=(session["auth_credentials"],))
thread.start()
return redirect(url_for("user_accounts"))
@app.route("/validateAccount", methods=["POST"])
@ -333,7 +320,7 @@ def validate_account() -> Tuple[Response, int]:
cache_key = f"view/{session['username']}/accounts"
cache.delete(cache_key)
# Run the NPM config update in a background thread
thread = threading.Thread(target=_update_npm_config_in_background, args=(session["auth_credentials"],))
thread = threading.Thread(target=_update_npm_config_in_background)
thread.start()
return jsonify(response_data), response.status_code
except requests.exceptions.RequestException as e:
@ -517,49 +504,34 @@ class NginxProxyManager:
def update_config_with_streams(config, streams):
# Get all stream names from the database
db_stream_names = {stream['streamName'] for stream in streams}
# Find all location blocks in the config (more accurate pattern)
location_blocks = re.findall(r'location\s+~\s+\^/(\w+)\(\.\*\)\$\s*\{[^}]*return\s+302\s+([^;]+);[^}]*\}', config)
existing_stream_names = {stream_name for stream_name, _ in location_blocks}
# Find all location blocks in the config
location_blocks = re.findall(r'location ~ \^/(\w+)\(\.\*\)\$ \{[^}]+\}', config)
# Remove location blocks that are not in the database
for stream_name in existing_stream_names:
for stream_name in location_blocks:
if stream_name not in db_stream_names:
print(f"Removing location block for stream: {stream_name}")
pattern = re.compile(f'location\\s+~\\s+\\^/{re.escape(stream_name)}\\(\\.\\*\\)\\$\\s*\\{{[^}}]*return\\s+302\\s+[^;]+;[^}}]*\\}}\\s*', re.DOTALL)
pattern = re.compile(f'location ~ \\^/{re.escape(stream_name)}\\(\\.\\*\\)\\$ {{[^}}]+}}\\s*', re.DOTALL)
config = pattern.sub('', config)
# Update existing stream URLs and create new ones
# Update existing stream URLs
for stream in streams:
stream_name = stream['streamName']
stream_url = stream['streamURL']
if stream_url: # Ensure there is a URL to update to
# Check if location block already exists for this stream
if stream_name in existing_stream_names:
# Update existing location block
pattern = re.compile(f'(location\\s+~\\s+\\^/{re.escape(stream_name)}\\(\\.\\*\\)\\$\\s*\\{{[^}}]*return\\s+302\\s+)([^;]+)(;[^}}]*\\}})', re.DOTALL)
config = pattern.sub(f'\\1{stream_url}/$1$is_args$args\\3', config)
else:
# Create new location block for this stream
new_location_block = f'location ~ ^/{stream_name}(.*)$ {{\n return 302 {stream_url}/$1$is_args$args;\n}}\n'
# Add the new block at the end of the config (before the last closing brace)
config = config.rstrip() + '\n' + new_location_block
print(f"Created new location block for stream: {stream_name}")
if stream_url: # Ensure there is a URL to update to
# Use a more specific regex to avoid replacing parts of other URLs
pattern = re.compile(f'(location ~ \\^/{re.escape(stream_name)}\\(\\.\\*\\)\\$ {{\\s*return 302 )([^;]+)(;\\s*}})')
config = pattern.sub(f'\\1{stream_url}/$1$is_args$args\\3', config)
return config
def _update_npm_config(credentials=None):
def _update_npm_config():
"""Helper function to update the NPM config."""
# Use provided credentials or get from session (for backward compatibility)
if credentials is None:
# This is for backward compatibility when called from background threads
# where session context might not be available
if not session.get('user_id') or int(session.get('user_id')) != 1:
print("Unauthorized attempt to update NPM config.")
return False
credentials = session.get("auth_credentials")
# If credentials are provided, we skip the session check as the user has already been authenticated
if not session.get('user_id') or int(session.get('user_id')) != 1:
print("Unauthorized attempt to update NPM config.")
return
npm = NginxProxyManager(app.config['NPM_HOST'], app.config['NPM_EMAIL'], app.config['NPM_PASSWORD'])
npm.login()
host = npm.get_proxy_host(9)
@ -567,8 +539,8 @@ def _update_npm_config(credentials=None):
current_config = host.get('advanced_config', '')
backend_url = f"{app.config['BACKEND_URL']}/get_all_stream_urls"
decoded_credentials = base64.b64decode(credentials).decode()
username, password = decoded_credentials.split(":", 1)
credentials = base64.b64decode(session["auth_credentials"]).decode()
username, password = credentials.split(":", 1)
auth = requests.auth.HTTPBasicAuth(username, password)
try:
@ -577,36 +549,28 @@ def _update_npm_config(credentials=None):
streams = response.json()
except requests.exceptions.RequestException as e:
print(f"Failed to fetch streams from backend: {e}")
return False
return
if streams:
print("Current Config:")
print(current_config)
new_config = update_config_with_streams(current_config, streams)
print("\nNew Config:")
print(new_config)
npm.update_proxy_host_config(9, new_config)
print("\nNPM config updated successfully.")
return True
print("NPM config updated successfully.")
else:
print("Failed to update NPM config.")
return False
def _update_npm_config_in_background(credentials):
def _update_npm_config_in_background():
with app.app_context():
_update_npm_config(credentials)
_update_npm_config()
@app.route('/update_host_9_config', methods=['POST'])
def update_host_9_config():
if not session.get('user_id') or int(session.get('user_id')) != 1:
return jsonify({'error': 'Unauthorized'}), 401
thread = threading.Thread(target=_update_npm_config_in_background, args=(session["auth_credentials"],))
thread = threading.Thread(target=_update_npm_config_in_background)
thread.start()
return jsonify({'message': 'NPM config update started in the background. Check logs for status.'}), 202
return jsonify({'message': 'NPM config update started in the background.'}), 202
if __name__ == "__main__":

View File

@ -2,7 +2,6 @@ import requests
import json
from datetime import datetime
from typing import List, Dict, Any, Optional
import time
# Create a session object to reuse TCP connections
session = requests.Session()
@ -41,16 +40,13 @@ def _make_api_request(
def get_urls(base_url: str, auth: str) -> List[Dict[str, Any]]:
"""Retrieves user account streams from the API."""
endpoint = f"getUserAccounts/streams?_t={int(time.time())}"
response = _make_api_request("GET", base_url, auth, endpoint)
response = _make_api_request("GET", base_url, auth, "getUserAccounts/streams")
return response.json() if response else []
def get_user_accounts(base_url: str, auth: str) -> List[Dict[str, Any]]:
"""Retrieves user accounts from the API."""
# Add cache-busting parameter to ensure fresh data
endpoint = f"getUserAccounts?_t={int(time.time())}"
response = _make_api_request("GET", base_url, auth, endpoint)
response = _make_api_request("GET", base_url, auth, "getUserAccounts")
if not response:
return []
@ -79,14 +75,7 @@ def add_user_account(
response = _make_api_request(
"POST", base_url, auth, "addAccount", payload=payload
)
if response and response.status_code == 200:
return True
elif response and response.status_code == 409:
# Account already exists
return False
else:
# Other error
return False
return response and response.status_code == 200
def get_stream_names(base_url: str, auth: str) -> List[str]:

View File

@ -119,62 +119,46 @@ def get_streams_from_db(db_host, db_user, db_pass, db_name, db_port):
def update_config_with_streams(config, streams):
# Get all stream names from the database
db_stream_names = {stream['streamName'] for stream in streams}
# Find all location blocks in the config (more accurate pattern)
location_blocks = re.findall(r'location\s+~\s+\^/(\w+)\(\.\*\)\$\s*\{[^}]*return\s+302\s+([^;]+);[^}]*\}', config)
existing_stream_names = {stream_name for stream_name, _ in location_blocks}
# Find all location blocks in the config
location_blocks = re.findall(r'location ~ \^/(\w+)\(\.\*\)\$ \{[^}]+\}', config)
# Remove location blocks that are not in the database
for stream_name in existing_stream_names:
for stream_name in location_blocks:
if stream_name not in db_stream_names:
print(f"Removing location block for stream: {stream_name}")
pattern = re.compile(f'location\\s+~\\s+\\^/{re.escape(stream_name)}\\(\\.\\*\\)\\$\\s*\\{{[^}}]*return\\s+302\\s+[^;]+;[^}}]*\\}}\\s*', re.DOTALL)
pattern = re.compile(f'location ~ \\^/{re.escape(stream_name)}\\(\\.\\*\\)\\$ {{[^}}]+}}\\s*', re.DOTALL)
config = pattern.sub('', config)
# Update existing stream URLs and create new ones
# Update existing stream URLs
for stream in streams:
stream_name = stream['streamName']
stream_url = stream['streamURL']
if stream_url: # Ensure there is a URL to update to
# Check if location block already exists for this stream
if stream_name in existing_stream_names:
# Update existing location block
pattern = re.compile(f'(location\\s+~\\s+\\^/{re.escape(stream_name)}\\(\\.\\*\\)\\$\\s*\\{{[^}}]*return\\s+302\\s+)([^;]+)(;[^}}]*\\}})', re.DOTALL)
config = pattern.sub(f'\\1{stream_url}/$1$is_args$args\\3', config)
else:
# Create new location block for this stream
new_location_block = f'location ~ ^/{stream_name}(.*)$ {{\n return 302 {stream_url}/$1$is_args$args;\n}}\n'
# Add the new block at the end of the config (before the last closing brace)
config = config.rstrip() + '\n' + new_location_block
print(f"Created new location block for stream: {stream_name}")
if stream_url: # Ensure there is a URL to update to
# Use a more specific regex to avoid replacing parts of other URLs
pattern = re.compile(f'(location ~ \\^/{re.escape(stream_name)}\\(\\.\\*\\)\\$ {{\\s*return 302 )([^;]+)(;\\s*}})')
config = pattern.sub(f'\\1{stream_url}/$1$is_args$args\\3', config)
return config
def main():
try:
npm = NginxProxyManager(app_config.NPM_HOST, app_config.NPM_EMAIL, app_config.NPM_PASSWORD)
npm.login()
host = npm.get_proxy_host(9)
if host:
current_config = host.get('advanced_config', '')
print("Current Config:")
print(current_config)
npm = NginxProxyManager(app_config.NPM_HOST, app_config.NPM_EMAIL, app_config.NPM_PASSWORD)
npm.login()
host = npm.get_proxy_host(9)
if host:
current_config = host.get('advanced_config', '')
print("Current Config:")
print(current_config)
streams = get_streams_from_db(app_config.DBHOST, app_config.DBUSER, app_config.DBPASS, app_config.DATABASE, app_config.DBPORT)
if streams:
new_config = update_config_with_streams(current_config, streams)
print("\nNew Config:")
print(new_config)
streams = get_streams_from_db(app_config.DBHOST, app_config.DBUSER, app_config.DBPASS, app_config.DATABASE, app_config.DBPORT)
if streams:
new_config = update_config_with_streams(current_config, streams)
print("\nNew Config:")
print(new_config)
# Apply the changes
npm.update_proxy_host_config(9, new_config)
print("\nChanges applied successfully.")
else:
print("No streams found in database.")
else:
print("Failed to get proxy host configuration.")
except Exception as e:
print(f"An error occurred: {e}")
# Uncomment the following line to apply the changes
npm.update_proxy_host_config(9, new_config)
print("\nTo apply the changes, uncomment the last line in the main function.")
if __name__ == "__main__":
main()