125 lines
4.0 KiB
Python
125 lines
4.0 KiB
Python
from flask import Blueprint, request, jsonify
|
|
from datetime import datetime
|
|
from pymongo.errors import DuplicateKeyError
|
|
from bson.objectid import ObjectId
|
|
import feedparser
|
|
from database import rss_feeds_collection
|
|
|
|
rss_bp = Blueprint('rss', __name__)
|
|
|
|
|
|
@rss_bp.route('/api/rss-feeds', methods=['GET'])
|
|
def get_rss_feeds():
|
|
"""Get all RSS feeds"""
|
|
try:
|
|
cursor = rss_feeds_collection.find().sort('created_at', -1)
|
|
feeds = []
|
|
for feed in cursor:
|
|
feeds.append({
|
|
'id': str(feed['_id']),
|
|
'name': feed.get('name', ''),
|
|
'url': feed.get('url', ''),
|
|
'active': feed.get('active', True),
|
|
'created_at': feed.get('created_at', '').isoformat() if feed.get('created_at') else ''
|
|
})
|
|
return jsonify({'feeds': feeds}), 200
|
|
except Exception as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
|
|
@rss_bp.route('/api/rss-feeds', methods=['POST'])
|
|
def add_rss_feed():
|
|
"""Add a new RSS feed"""
|
|
data = request.json
|
|
name = data.get('name', '').strip()
|
|
url = data.get('url', '').strip()
|
|
|
|
if not name or not url:
|
|
return jsonify({'error': 'Name and URL are required'}), 400
|
|
|
|
if not url.startswith('http://') and not url.startswith('https://'):
|
|
return jsonify({'error': 'URL must start with http:// or https://'}), 400
|
|
|
|
try:
|
|
# Test if the RSS feed is valid
|
|
try:
|
|
feed = feedparser.parse(url)
|
|
if not feed.entries:
|
|
return jsonify({'error': 'Invalid RSS feed or no entries found'}), 400
|
|
except Exception as e:
|
|
return jsonify({'error': f'Failed to parse RSS feed: {str(e)}'}), 400
|
|
|
|
feed_doc = {
|
|
'name': name,
|
|
'url': url,
|
|
'active': True,
|
|
'created_at': datetime.utcnow()
|
|
}
|
|
|
|
try:
|
|
result = rss_feeds_collection.insert_one(feed_doc)
|
|
return jsonify({
|
|
'message': 'RSS feed added successfully',
|
|
'id': str(result.inserted_id)
|
|
}), 201
|
|
except DuplicateKeyError:
|
|
return jsonify({'error': 'RSS feed URL already exists'}), 409
|
|
|
|
except Exception as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
|
|
@rss_bp.route('/api/rss-feeds/<feed_id>', methods=['DELETE'])
|
|
def remove_rss_feed(feed_id):
|
|
"""Remove an RSS feed"""
|
|
try:
|
|
# Validate ObjectId
|
|
try:
|
|
obj_id = ObjectId(feed_id)
|
|
except Exception:
|
|
return jsonify({'error': 'Invalid feed ID'}), 400
|
|
|
|
result = rss_feeds_collection.delete_one({'_id': obj_id})
|
|
|
|
if result.deleted_count > 0:
|
|
return jsonify({'message': 'RSS feed removed successfully'}), 200
|
|
else:
|
|
return jsonify({'error': 'RSS feed not found'}), 404
|
|
|
|
except Exception as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
|
|
@rss_bp.route('/api/rss-feeds/<feed_id>/toggle', methods=['PATCH'])
|
|
def toggle_rss_feed(feed_id):
|
|
"""Toggle RSS feed active status"""
|
|
try:
|
|
# Validate ObjectId
|
|
try:
|
|
obj_id = ObjectId(feed_id)
|
|
except Exception:
|
|
return jsonify({'error': 'Invalid feed ID'}), 400
|
|
|
|
# Get current status
|
|
feed = rss_feeds_collection.find_one({'_id': obj_id})
|
|
if not feed:
|
|
return jsonify({'error': 'RSS feed not found'}), 404
|
|
|
|
# Toggle status
|
|
new_status = not feed.get('active', True)
|
|
result = rss_feeds_collection.update_one(
|
|
{'_id': obj_id},
|
|
{'$set': {'active': new_status}}
|
|
)
|
|
|
|
if result.modified_count > 0:
|
|
return jsonify({
|
|
'message': f'RSS feed {"activated" if new_status else "deactivated"} successfully',
|
|
'active': new_status
|
|
}), 200
|
|
else:
|
|
return jsonify({'error': 'Failed to update RSS feed'}), 500
|
|
|
|
except Exception as e:
|
|
return jsonify({'error': str(e)}), 500
|