import os import json import time import requests import math from datetime import datetime, timezone, timedelta from flask import Flask, request, jsonify from flask_cors import CORS app = Flask(__name__) # configure daily limit and data directory. DAILY_LIMIT = 50 DATA_DIR = 'guestbook' #get current UTC time and convert it to BMT now_utc = datetime.now(timezone.utc) bmt = now_utc + timedelta(hours=1) currentDate = bmt.strftime('%Y-%m-%d') submissionCountDay = 0 frontend_url = os.environ.get("FRONTEND_URL","*") topic = os.environ.get("NTFY_TOPIC") CORS(app, resources={r"/*": {"origins": frontend_url}}) if not os.path.exists(DATA_DIR): os.makedirs(DATA_DIR) @app.route('/comments', methods=['GET']) def getComments(): comments = [] try: files = sorted([f for f in os.listdir(DATA_DIR) if f.endswith('.json')], reverse=True) for filename in files: filepath = os.path.join(DATA_DIR, filename) with open(filepath, 'r', encoding='utf-8') as f: try: data = json.load(f) comments.append(data) except json.JSONDecodeError: continue return jsonify(comments) except Exception as e: return jsonify({"error": str(e)}), 500 @app.route('/comments', methods=['POST']) def addComment(): global currentDate, submissionCountDay # Check date today_str = datetime.now().strftime('%Y-%m-%d') if today_str != currentDate: currentDate = today_str submissionCountDay = 0 # Check limit if submissionCountDay >= DAILY_LIMIT: return jsonify({"error": "Guestbook full for the day, try tomorrow!"}), 403 data = request.json name = data.get('name', '').strip() message = data.get('message', '').strip() website = data.get('website', '').strip() if not name or not message: return jsonify({"error": "Missing fields"}), 400 #URL cleanup if website: # If forgot http://, add it for them if not website.startswith(('http://', 'https://')): website = 'https://' + website date_str=time.strftime("%d-%m-%Y") itime_beats=itime() entry = { 'name': name, 'message': message, 'website': website, 'date': f"{date_str} @{itime_beats:03d}" } now = datetime.now() readable_time = now.strftime('%Y-%m-%d_%H-%M-%S') filename = f"{readable_time}.json" filepath = os.path.join(DATA_DIR, filename) try: with open(filepath, 'x', encoding='utf-8') as f: json.dump(entry, f) except FileExistsError: filename = f"{readable_time}_2.json" filepath = os.path.join(DATA_DIR, filename) with open(filepath, 'x', encoding='utf-8') as f: json.dump(entry, f) send_ntfy_notification(name, message) submissionCountDay += 1 return jsonify({"status": "success"}) #helper functions: # Source - https://stackoverflow.com/a/51722192 # Posted by kernel # Retrieved 2026-01-29, License - CC BY-SA 4.0 #thanks @kernel! def itime(): """Calculate and return Swatch Internet Time :returns: No. of beats (Swatch Internet Time) :rtype: float """ midnight = bmt.replace(hour=0, minute=0, second=0, microsecond=0) seconds_passed = (bmt - midnight).total_seconds() beats = int(math.floor(seconds_passed / 86.4)) # if beats > 1000: # beats -= 1000 # elif beats < 0: # beats += 1000 return beats def send_ntfy_notification(name, message): if not topic: return try: requests.post(f"https://ntfy.sh/{topic}", data=f"{name} wrote: {message}", headers={ "Title": "Someone Signed Your Guestbook!" }) except Exception as e: print(f"Notification failed: {e}") if __name__ == '__main__': app.run(host='0.0.0.0', port=5001)