Compare commits

...

4 Commits

Author SHA1 Message Date
0e56ca16bb Bump version: 1.3.4 → 1.3.5
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 1m31s
2025-07-19 23:14:09 +01:00
b673a232b1 looking for extra urls 2025-07-19 23:13:48 +01:00
64b54e959e lets deploy and see 2025-07-19 11:56:30 +01:00
aeaac5fd4e extra url modifications 2025-07-19 11:31:16 +01:00
9 changed files with 100 additions and 9 deletions

View File

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

View File

@ -1 +1 @@
1.3.4
1.3.5

View File

@ -33,6 +33,9 @@ ENV FLASK_APP=ktvmanager.main:create_app
# Copy application code
COPY . .
# Debugging step to verify file presence
RUN ls -la /app/ktvmanager/lib
# Handle versioning
ARG VERSION
RUN if [ -n "$VERSION" ]; then echo $VERSION > VERSION; fi

View File

@ -53,9 +53,10 @@ def send_expiry_notifications(app) -> None:
for account in expiring_accounts:
expiry_date = datetime.fromtimestamp(account['expiaryDate'])
days_to_expiry = (expiry_date - now).days
days_to_expiry = (expiry_date.date() - now.date()).days
if days_to_expiry == 30 or days_to_expiry == 7:
print(f"Found expiring account: {account['username']}")
user_id = account['user_id']
subscriptions = get_push_subscriptions(user_id)
for sub in subscriptions:
@ -67,8 +68,11 @@ def send_expiry_notifications(app) -> None:
if last_notified and last_notified.date() == now.date():
continue
message = f"Your account {account['username']} is due to expire in {days_to_expiry} days."
send_notification(sub['subscription_json'], message)
message = {
"title": "Account Expiry Warning",
"body": f"Your account {account['username']} is due to expire in {days_to_expiry} days."
}
send_notification(sub['subscription_json'], json.dumps(message))
# Update the last notified timestamp
update_last_notified_query = "UPDATE push_subscriptions SET last_notified = %s WHERE id = %s"

View File

@ -237,3 +237,14 @@ def get_push_subscriptions(user_id: Optional[int] = None) -> List[Dict[str, Any]
else:
query = "SELECT * FROM push_subscriptions"
return _execute_query(query)
def delete_push_subscription(subscription_json: str) -> None:
"""Deletes a push subscription from the database.
Args:
subscription_json: The push subscription information as a JSON string.
"""
query = "DELETE FROM push_subscriptions WHERE subscription_json = %s"
params = (subscription_json,)
_execute_query(query, params)

View File

@ -1,8 +1,11 @@
import json
from flask import current_app
from pywebpush import webpush, WebPushException
from ktvmanager.lib.database import delete_push_subscription
def send_notification(subscription_info, message_body):
def send_notification(subscription_json, message_body):
try:
subscription_info = json.loads(subscription_json)
webpush(
subscription_info=subscription_info,
data=message_body,
@ -11,7 +14,6 @@ def send_notification(subscription_info, message_body):
)
except WebPushException as ex:
print(f"Web push error: {ex}")
# You might want to remove the subscription if it's invalid
if ex.response and ex.response.status_code == 410:
print("Subscription is no longer valid, removing from DB.")
# Add logic to remove the subscription from your database
delete_push_subscription(subscription_json)

View File

@ -5,6 +5,7 @@ from dotenv import load_dotenv
from ktvmanager.config import DevelopmentConfig, ProductionConfig
from routes.api import api_blueprint
from routes.dns import dns_bp
from routes.extra_urls import extra_urls_bp
from ktvmanager.lib.database import initialize_db_pool
from ktvmanager.account_checker import send_expiry_notifications
from apscheduler.schedulers.background import BackgroundScheduler
@ -31,6 +32,7 @@ def create_app():
# Register blueprints
app.register_blueprint(api_blueprint)
app.register_blueprint(dns_bp)
app.register_blueprint(extra_urls_bp)
@app.route('/check-expiry', methods=['POST'])
def check_expiry():

View File

@ -237,7 +237,7 @@ def send_test_notification_route(username: str, password: str) -> Response:
for sub in subscriptions:
try:
send_notification(json.loads(sub['subscription_json']), message_body)
send_notification(sub['subscription_json'], message_body)
success_count += 1
except Exception as e:
print(f"Error sending notification to subscription ID {sub.get('id', 'N/A')}: {e}")

69
routes/extra_urls.py Normal file
View File

@ -0,0 +1,69 @@
from flask import Blueprint, request, jsonify
import os
extra_urls_bp = Blueprint('extra_urls', __name__)
EXTRA_URLS_FILE = os.path.join(os.path.dirname(__file__), '..', 'ktvmanager', 'lib', 'extra_urls.txt')
def read_extra_urls_list():
if not os.path.exists(EXTRA_URLS_FILE):
return []
with open(EXTRA_URLS_FILE, 'r') as f:
return [line.strip() for line in f.readlines() if line.strip()]
def write_extra_urls_list(extra_urls_list):
with open(EXTRA_URLS_FILE, 'w') as f:
for item in extra_urls_list:
f.write(f"{item}\n")
@extra_urls_bp.route('/extra_urls', methods=['GET'])
def get_extra_urls_list():
"""Gets the list of extra URLs."""
return jsonify(read_extra_urls_list())
@extra_urls_bp.route('/extra_urls', methods=['POST'])
def add_extra_url():
"""Adds a new extra URL."""
data = request.get_json()
if not data or 'extra_url' not in data:
return jsonify({'error': 'Missing extra_url in request body'}), 400
extra_url = data.get('extra_url')
if not extra_url:
return jsonify({'error': 'Extra URL cannot be empty.'}), 400
extra_urls_list = read_extra_urls_list()
if extra_url in extra_urls_list:
return jsonify({'message': 'Extra URL already exists.'}), 200
extra_urls_list.append(extra_url)
write_extra_urls_list(extra_urls_list)
return jsonify({'message': 'Extra URL added successfully.'}), 201
@extra_urls_bp.route('/extra_urls', methods=['DELETE'])
def remove_extra_url():
"""Removes an extra URL."""
data = request.get_json()
if not data or 'extra_url' not in data:
return jsonify({'error': 'Missing extra_url in request body'}), 400
extra_url = data.get('extra_url')
if not extra_url:
return jsonify({'error': 'Extra URL cannot be empty.'}), 400
extra_urls_list = read_extra_urls_list()
if extra_url not in extra_urls_list:
return jsonify({'error': 'Extra URL not found.'}), 404
extra_urls_list.remove(extra_url)
write_extra_urls_list(extra_urls_list)
return jsonify({'message': 'Extra URL removed successfully.'}), 200
@extra_urls_bp.route('/extra_urls_file', methods=['GET'])
def get_extra_urls_file():
"""Gets the content of the extra_urls.txt file."""
if not os.path.exists(EXTRA_URLS_FILE):
return "File not found", 404
with open(EXTRA_URLS_FILE, 'r') as f:
content = f.read()
return Response(content, mimetype='text/plain')