from flask import Blueprint, request, jsonify from datetime import datetime from pymongo.errors import DuplicateKeyError from database import subscribers_collection subscription_bp = Blueprint('subscription', __name__) @subscription_bp.route('/api/subscribe', methods=['POST']) def subscribe(): """Subscribe a user to the newsletter""" data = request.json email = data.get('email', '').strip().lower() if not email or '@' not in email: return jsonify({'error': 'Invalid email address'}), 400 try: subscriber_doc = { 'email': email, 'subscribed_at': datetime.utcnow(), 'status': 'active' } # Try to insert, if duplicate key error, subscriber already exists try: subscribers_collection.insert_one(subscriber_doc) return jsonify({'message': 'Successfully subscribed!'}), 201 except DuplicateKeyError: # Check if subscriber is active existing = subscribers_collection.find_one({'email': email}) if existing and existing.get('status') == 'active': return jsonify({'message': 'Email already subscribed'}), 200 else: # Reactivate if previously unsubscribed subscribers_collection.update_one( {'email': email}, {'$set': {'status': 'active', 'subscribed_at': datetime.utcnow()}} ) return jsonify({'message': 'Successfully re-subscribed!'}), 200 except Exception as e: return jsonify({'error': str(e)}), 500 @subscription_bp.route('/api/unsubscribe', methods=['POST']) def unsubscribe(): """Unsubscribe a user from the newsletter""" data = request.json email = data.get('email', '').strip().lower() try: result = subscribers_collection.update_one( {'email': email}, {'$set': {'status': 'inactive'}} ) if result.matched_count > 0: return jsonify({'message': 'Successfully unsubscribed'}), 200 else: return jsonify({'error': 'Email not found in subscribers'}), 404 except Exception as e: return jsonify({'error': str(e)}), 500 @subscription_bp.route('/api/subscribers', methods=['GET']) def list_subscribers(): """List all subscribers with optional status filter""" try: # Get status filter from query params (default: all) status = request.args.get('status', None) # Build query query = {} if status: query['status'] = status # Fetch subscribers subscribers = list(subscribers_collection.find( query, {'_id': 0, 'email': 1, 'subscribed_at': 1, 'status': 1} ).sort('subscribed_at', -1)) # Convert datetime to ISO format for sub in subscribers: if 'subscribed_at' in sub: sub['subscribed_at'] = sub['subscribed_at'].isoformat() return jsonify({ 'subscribers': subscribers, 'total': len(subscribers) }), 200 except Exception as e: return jsonify({'error': str(e)}), 500 @subscription_bp.route('/api/subscribers/', methods=['DELETE']) def remove_subscriber(email): """Permanently remove a subscriber from the database""" try: email = email.strip().lower() result = subscribers_collection.delete_one({'email': email}) if result.deleted_count > 0: return jsonify({'message': f'Subscriber {email} permanently removed'}), 200 else: return jsonify({'error': 'Email not found in subscribers'}), 404 except Exception as e: return jsonify({'error': str(e)}), 500