This commit is contained in:
2025-11-12 22:33:56 +01:00
parent 95669fd211
commit 45df834d5b
12 changed files with 1172 additions and 240 deletions

View File

@@ -8,36 +8,69 @@ subscription_bp = Blueprint('subscription', __name__)
@subscription_bp.route('/api/subscribe', methods=['POST'])
def subscribe():
"""Subscribe a user to the newsletter"""
"""Subscribe a user to the newsletter with category preferences"""
data = request.json
email = data.get('email', '').strip().lower()
# Get valid categories from RSS feeds
from database import rss_feeds_collection
valid_categories = rss_feeds_collection.distinct('category')
categories = data.get('categories', valid_categories) # Default: all categories
if not email or '@' not in email:
return jsonify({'error': 'Invalid email address'}), 400
# Validate categories
if not isinstance(categories, list) or not categories:
categories = valid_categories # Default to all if invalid
else:
# Filter to only valid categories (categories that exist in RSS feeds)
categories = [c for c in categories if c in valid_categories]
if not categories:
categories = valid_categories # Default to all if none valid
try:
subscriber_doc = {
'email': email,
'subscribed_at': datetime.utcnow(),
'status': 'active'
'status': 'active',
'categories': categories
}
# Try to insert, if duplicate key error, subscriber already exists
try:
subscribers_collection.insert_one(subscriber_doc)
return jsonify({'message': 'Successfully subscribed!'}), 201
return jsonify({
'message': 'Successfully subscribed!',
'categories': categories
}), 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
# Update categories even if already subscribed
subscribers_collection.update_one(
{'email': email},
{'$set': {'categories': categories}}
)
return jsonify({
'message': 'Email already subscribed. Preferences updated!',
'categories': categories
}), 200
else:
# Reactivate if previously unsubscribed
subscribers_collection.update_one(
{'email': email},
{'$set': {'status': 'active', 'subscribed_at': datetime.utcnow()}}
{'$set': {
'status': 'active',
'subscribed_at': datetime.utcnow(),
'categories': categories
}}
)
return jsonify({'message': 'Successfully re-subscribed!'}), 200
return jsonify({
'message': 'Successfully re-subscribed!',
'categories': categories
}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
@@ -95,6 +128,34 @@ def list_subscribers():
return jsonify({'error': str(e)}), 500
@subscription_bp.route('/api/subscribers/<email>', methods=['GET'])
def get_subscriber(email):
"""Get a single subscriber's information"""
try:
email = email.strip().lower()
subscriber = subscribers_collection.find_one(
{'email': email},
{'_id': 0, 'email': 1, 'categories': 1, 'status': 1, 'subscribed_at': 1}
)
if subscriber:
# Convert datetime to ISO format
if 'subscribed_at' in subscriber:
subscriber['subscribed_at'] = subscriber['subscribed_at'].isoformat()
# Ensure categories field exists
if 'categories' not in subscriber:
subscriber['categories'] = ['general', 'local', 'sports']
return jsonify(subscriber), 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/<email>', methods=['DELETE'])
def remove_subscriber(email):
"""Permanently remove a subscriber from the database"""
@@ -110,3 +171,68 @@ def remove_subscriber(email):
except Exception as e:
return jsonify({'error': str(e)}), 500
@subscription_bp.route('/api/admin/subscribers/delete-all', methods=['DELETE'])
def delete_all_subscribers():
"""Delete all subscribers (admin only)"""
try:
result = subscribers_collection.delete_many({})
return jsonify({
'message': f'Successfully deleted {result.deleted_count} subscribers',
'deleted_count': result.deleted_count
}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
@subscription_bp.route('/api/categories', methods=['GET'])
def get_categories():
"""Get available newsletter categories from RSS feeds"""
from database import rss_feeds_collection
# Get unique categories from RSS feeds
categories_from_db = rss_feeds_collection.distinct('category')
# Category metadata
category_info = {
'general': {
'name': 'Top Trending',
'description': 'Top trending news and updates',
'icon': '🔥'
},
'local': {
'name': 'Local Events',
'description': 'Local events, culture, and community news',
'icon': '🏛️'
},
'sports': {
'name': 'Sports',
'description': 'Sports news and updates',
'icon': ''
},
'science': {
'name': 'Science & Tech',
'description': 'Science and technology news',
'icon': '🔬'
}
}
# Build category list
categories = []
for cat_id in sorted(categories_from_db):
info = category_info.get(cat_id, {
'name': cat_id.title(),
'description': f'{cat_id.title()} news',
'icon': '📄'
})
categories.append({
'id': cat_id,
'name': info['name'],
'description': info['description'],
'icon': info['icon']
})
return jsonify({'categories': categories}), 200