feat: add ntfy push notifications for new requests
- Add ntfy server/topic settings in /admin/settings next to Hermes API key - POST a push notification to the configured topic on every new customer request - Add a Send Test ntfy button to verify configuration - Add requests dependency for ntfy HTTP calls - Bump version to 0.5.6
This commit is contained in:
parent
410a9cf021
commit
a56f6e498b
6 changed files with 105 additions and 8 deletions
68
app.py
68
app.py
|
|
@ -64,6 +64,9 @@ from models import SCHEMA, get_requests_by_email, log_revision, list_revision_hi
|
|||
from mutagen.mp3 import MP3
|
||||
from mutagen.easyid3 import EasyID3
|
||||
|
||||
# HTTP client for ntfy push notifications
|
||||
import requests
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Genre / decade helpers
|
||||
|
|
@ -411,6 +414,36 @@ def mask_api_key(key):
|
|||
return '*' * (len(key) - 6) + key[-6:]
|
||||
|
||||
|
||||
def get_ntfy_config():
|
||||
"""Return the effective ntfy server URL and topic from runtime settings."""
|
||||
cfg = load_booth_settings()
|
||||
return {
|
||||
'server': cfg.get('ntfy_server', ''),
|
||||
'topic': cfg.get('ntfy_topic', ''),
|
||||
}
|
||||
|
||||
|
||||
def send_ntfy(message, title='Theme Song Booth', priority='default', tags='bell'):
|
||||
"""Send a push notification to the configured ntfy topic, if configured."""
|
||||
ntfy = get_ntfy_config()
|
||||
server = ntfy.get('server', '').rstrip('/')
|
||||
topic = ntfy.get('topic', '').strip()
|
||||
if not server or not topic:
|
||||
return False
|
||||
|
||||
url = f"{server}/{topic}"
|
||||
headers = {
|
||||
'Title': title,
|
||||
'Priority': priority,
|
||||
'Tags': tags,
|
||||
}
|
||||
try:
|
||||
resp = requests.post(url, data=message.encode('utf-8'), headers=headers, timeout=10)
|
||||
return resp.status_code in (200, 202)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def sign_prompt_callback(rid, expires_at=None):
|
||||
"""
|
||||
Create a signed callback token for a specific request ID.
|
||||
|
|
@ -559,6 +592,18 @@ def request_form():
|
|||
return render_template('request.html', form=form_data, decades=DECADES, genres=MUSIC_GENRES), 400
|
||||
rid = create_request(**form_data)
|
||||
|
||||
# Notify operator via ntfy when a new request comes in.
|
||||
try:
|
||||
send_ntfy(
|
||||
f"New request #{rid} from {form_data['name']} ({form_data['email']})\nStyle: {form_data['style_genre'] or '-'}",
|
||||
title='New Theme Song Request',
|
||||
priority='high',
|
||||
tags='musical_note'
|
||||
)
|
||||
except Exception:
|
||||
# Push notification failure should never break the customer form.
|
||||
pass
|
||||
|
||||
# Send confirmation email with a summary of what the customer asked for.
|
||||
req = get_request_by_id(rid)
|
||||
if req:
|
||||
|
|
@ -1626,6 +1671,28 @@ def admin_settings():
|
|||
flash('Hermes API key is managed via the HERMES_API_KEY environment variable.', 'info')
|
||||
return redirect(url_for('admin_settings'))
|
||||
|
||||
elif action == 'save_ntfy':
|
||||
# Update ntfy push notification server/topic from the settings form.
|
||||
cfg = load_booth_settings()
|
||||
cfg['ntfy_server'] = request.form.get('ntfy_server', '').strip().rstrip('/')
|
||||
cfg['ntfy_topic'] = request.form.get('ntfy_topic', '').strip()
|
||||
save_booth_settings(cfg)
|
||||
flash('ntfy notification settings saved.', 'success')
|
||||
return redirect(url_for('admin_settings'))
|
||||
|
||||
elif action == 'send_test_ntfy':
|
||||
# Send a test push notification to the configured ntfy topic.
|
||||
ntfy = get_ntfy_config()
|
||||
if not ntfy['server'] or not ntfy['topic']:
|
||||
flash('Configure ntfy server and topic first.', 'error')
|
||||
return redirect(url_for('admin_settings'))
|
||||
ok = send_ntfy('This is a test push notification from the Trollgorithm Theme Song Booth.', title='Test Notification', priority='high', tags='test_tube')
|
||||
if ok:
|
||||
flash('Test ntfy notification sent.', 'success')
|
||||
else:
|
||||
flash('Failed to send ntfy test notification. Check server and topic.', 'error')
|
||||
return redirect(url_for('admin_settings'))
|
||||
|
||||
return render_template(
|
||||
'admin/settings.html',
|
||||
health=health,
|
||||
|
|
@ -1653,6 +1720,7 @@ def admin_settings():
|
|||
hermes_key_set=hermes_key_set,
|
||||
hermes_key_just_generated=hermes_key_just_generated,
|
||||
version=current_app.config['VERSION'],
|
||||
ntfy=runtime_settings,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Reference in a new issue