final stage of the app
This commit is contained in:
304
app/routes/api.py
Normal file
304
app/routes/api.py
Normal file
@@ -0,0 +1,304 @@
|
||||
"""
|
||||
API routes for QR Code Manager
|
||||
"""
|
||||
|
||||
import os
|
||||
import io
|
||||
import base64
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from flask import Blueprint, request, jsonify, send_file
|
||||
from app.utils.auth import login_required
|
||||
from app.utils.qr_generator import QRCodeGenerator
|
||||
from app.utils.link_manager import LinkPageManager
|
||||
from app.utils.data_manager import QRDataManager
|
||||
|
||||
bp = Blueprint('api', __name__)
|
||||
|
||||
# Initialize managers
|
||||
qr_generator = QRCodeGenerator()
|
||||
link_manager = LinkPageManager()
|
||||
data_manager = QRDataManager()
|
||||
|
||||
# Configuration for file uploads
|
||||
UPLOAD_FOLDER = 'app/static/qr_codes'
|
||||
LOGOS_FOLDER = 'app/static/logos'
|
||||
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||
os.makedirs(LOGOS_FOLDER, exist_ok=True)
|
||||
|
||||
@bp.route('/generate', methods=['POST'])
|
||||
@login_required
|
||||
def generate_qr():
|
||||
"""Generate QR code API endpoint"""
|
||||
try:
|
||||
data = request.json
|
||||
|
||||
# Extract QR code content
|
||||
qr_type = data.get('type', 'text')
|
||||
content = data.get('content', '')
|
||||
|
||||
# Process content based on type
|
||||
if qr_type == 'url':
|
||||
qr_content = content if content.startswith(('http://', 'https://')) else f'https://{content}'
|
||||
elif qr_type == 'wifi':
|
||||
wifi_data = data.get('wifi', {})
|
||||
qr_content = f"WIFI:T:{wifi_data.get('security', 'WPA')};S:{wifi_data.get('ssid', '')};P:{wifi_data.get('password', '')};H:{wifi_data.get('hidden', 'false')};;"
|
||||
elif qr_type == 'email':
|
||||
email_data = data.get('email', {})
|
||||
qr_content = f"mailto:{email_data.get('email', '')}?subject={email_data.get('subject', '')}&body={email_data.get('body', '')}"
|
||||
elif qr_type == 'phone':
|
||||
qr_content = f"tel:{content}"
|
||||
elif qr_type == 'sms':
|
||||
sms_data = data.get('sms', {})
|
||||
qr_content = f"smsto:{sms_data.get('phone', '')}:{sms_data.get('message', '')}"
|
||||
elif qr_type == 'vcard':
|
||||
vcard_data = data.get('vcard', {})
|
||||
qr_content = f"""BEGIN:VCARD
|
||||
VERSION:3.0
|
||||
FN:{vcard_data.get('name', '')}
|
||||
ORG:{vcard_data.get('organization', '')}
|
||||
TEL:{vcard_data.get('phone', '')}
|
||||
EMAIL:{vcard_data.get('email', '')}
|
||||
URL:{vcard_data.get('website', '')}
|
||||
END:VCARD"""
|
||||
else: # text
|
||||
qr_content = content
|
||||
|
||||
# Extract styling options
|
||||
settings = {
|
||||
'size': data.get('size', 10),
|
||||
'border': data.get('border', 4),
|
||||
'foreground_color': data.get('foreground_color', '#000000'),
|
||||
'background_color': data.get('background_color', '#FFFFFF'),
|
||||
'style': data.get('style', 'square')
|
||||
}
|
||||
|
||||
# Generate QR code
|
||||
qr_img = qr_generator.generate_qr_code(qr_content, settings)
|
||||
|
||||
# Add logo if provided
|
||||
logo_path = data.get('logo_path')
|
||||
if logo_path and os.path.exists(logo_path):
|
||||
qr_img = qr_generator.add_logo(qr_img, logo_path)
|
||||
|
||||
# Convert to base64
|
||||
img_buffer = io.BytesIO()
|
||||
qr_img.save(img_buffer, format='PNG')
|
||||
img_buffer.seek(0)
|
||||
img_base64 = base64.b64encode(img_buffer.getvalue()).decode()
|
||||
|
||||
# Save QR code record
|
||||
qr_id = data_manager.save_qr_record(qr_type, qr_content, settings, img_base64)
|
||||
|
||||
# Save image file
|
||||
img_path = os.path.join(UPLOAD_FOLDER, f'{qr_id}.png')
|
||||
qr_img.save(img_path)
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'qr_id': qr_id,
|
||||
'image_data': f'data:image/png;base64,{img_base64}',
|
||||
'download_url': f'/api/download/{qr_id}'
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@bp.route('/download/<qr_id>')
|
||||
@login_required
|
||||
def download_qr(qr_id):
|
||||
"""Download QR code"""
|
||||
try:
|
||||
img_path = os.path.join(UPLOAD_FOLDER, f'{qr_id}.png')
|
||||
if os.path.exists(img_path):
|
||||
return send_file(img_path, as_attachment=True, download_name=f'qr_code_{qr_id}.png')
|
||||
else:
|
||||
return jsonify({'error': 'QR code not found'}), 404
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@bp.route('/qr_codes')
|
||||
@login_required
|
||||
def list_qr_codes():
|
||||
"""List all generated QR codes"""
|
||||
return jsonify(data_manager.list_qr_codes())
|
||||
|
||||
@bp.route('/qr_codes/<qr_id>')
|
||||
@login_required
|
||||
def get_qr_code(qr_id):
|
||||
"""Get specific QR code details"""
|
||||
qr_data = data_manager.get_qr_record(qr_id)
|
||||
if qr_data:
|
||||
return jsonify(qr_data)
|
||||
else:
|
||||
return jsonify({'error': 'QR code not found'}), 404
|
||||
|
||||
@bp.route('/qr_codes/<qr_id>', methods=['DELETE'])
|
||||
@login_required
|
||||
def delete_qr_code(qr_id):
|
||||
"""Delete QR code"""
|
||||
try:
|
||||
if data_manager.qr_exists(qr_id):
|
||||
# Remove from database
|
||||
data_manager.delete_qr_record(qr_id)
|
||||
|
||||
# Remove image file
|
||||
img_path = os.path.join(UPLOAD_FOLDER, f'{qr_id}.png')
|
||||
if os.path.exists(img_path):
|
||||
os.remove(img_path)
|
||||
|
||||
return jsonify({'success': True})
|
||||
else:
|
||||
return jsonify({'error': 'QR code not found'}), 404
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@bp.route('/upload_logo', methods=['POST'])
|
||||
@login_required
|
||||
def upload_logo():
|
||||
"""Upload logo for QR code"""
|
||||
try:
|
||||
if 'logo' not in request.files:
|
||||
return jsonify({'error': 'No logo file provided'}), 400
|
||||
|
||||
file = request.files['logo']
|
||||
if file.filename == '':
|
||||
return jsonify({'error': 'No file selected'}), 400
|
||||
|
||||
# Save logo
|
||||
logo_id = str(uuid.uuid4())
|
||||
logo_extension = file.filename.rsplit('.', 1)[1].lower()
|
||||
logo_filename = f'{logo_id}.{logo_extension}'
|
||||
logo_path = os.path.join(LOGOS_FOLDER, logo_filename)
|
||||
file.save(logo_path)
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'logo_path': logo_path,
|
||||
'logo_id': logo_id
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
# Dynamic Link Pages API Routes
|
||||
|
||||
@bp.route('/create_link_page', methods=['POST'])
|
||||
@login_required
|
||||
def create_link_page():
|
||||
"""Create a new dynamic link page and QR code"""
|
||||
try:
|
||||
data = request.json
|
||||
title = data.get('title', 'My Links')
|
||||
description = data.get('description', 'Collection of useful links')
|
||||
|
||||
# Create the link page
|
||||
page_id = link_manager.create_link_page(title, description)
|
||||
|
||||
# Create QR code pointing to the link page
|
||||
page_url = f"{request.url_root}links/{page_id}"
|
||||
|
||||
settings = {
|
||||
'size': data.get('size', 10),
|
||||
'border': data.get('border', 4),
|
||||
'foreground_color': data.get('foreground_color', '#000000'),
|
||||
'background_color': data.get('background_color', '#FFFFFF'),
|
||||
'style': data.get('style', 'square')
|
||||
}
|
||||
|
||||
# Generate QR code
|
||||
qr_img = qr_generator.generate_qr_code(page_url, settings)
|
||||
|
||||
# Convert to base64
|
||||
img_buffer = io.BytesIO()
|
||||
qr_img.save(img_buffer, format='PNG')
|
||||
img_buffer.seek(0)
|
||||
img_base64 = base64.b64encode(img_buffer.getvalue()).decode()
|
||||
|
||||
# Save QR code record
|
||||
qr_id = data_manager.save_qr_record('link_page', page_url, settings, img_base64, page_id)
|
||||
|
||||
# Save image file
|
||||
img_path = os.path.join(UPLOAD_FOLDER, f'{qr_id}.png')
|
||||
qr_img.save(img_path)
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'qr_id': qr_id,
|
||||
'page_id': page_id,
|
||||
'page_url': page_url,
|
||||
'edit_url': f"{request.url_root}edit/{page_id}",
|
||||
'image_data': f'data:image/png;base64,{img_base64}',
|
||||
'download_url': f'/api/download/{qr_id}'
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@bp.route('/link_pages/<page_id>/links', methods=['POST'])
|
||||
@login_required
|
||||
def add_link_to_page(page_id):
|
||||
"""Add a link to a page"""
|
||||
try:
|
||||
data = request.json
|
||||
title = data.get('title', '')
|
||||
url = data.get('url', '')
|
||||
description = data.get('description', '')
|
||||
|
||||
if not title or not url:
|
||||
return jsonify({'error': 'Title and URL are required'}), 400
|
||||
|
||||
success = link_manager.add_link(page_id, title, url, description)
|
||||
|
||||
if success:
|
||||
return jsonify({'success': True})
|
||||
else:
|
||||
return jsonify({'error': 'Page not found'}), 404
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@bp.route('/link_pages/<page_id>/links/<link_id>', methods=['PUT'])
|
||||
@login_required
|
||||
def update_link_in_page(page_id, link_id):
|
||||
"""Update a link in a page"""
|
||||
try:
|
||||
data = request.json
|
||||
title = data.get('title')
|
||||
url = data.get('url')
|
||||
description = data.get('description')
|
||||
|
||||
success = link_manager.update_link(page_id, link_id, title, url, description)
|
||||
|
||||
if success:
|
||||
return jsonify({'success': True})
|
||||
else:
|
||||
return jsonify({'error': 'Page or link not found'}), 404
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@bp.route('/link_pages/<page_id>/links/<link_id>', methods=['DELETE'])
|
||||
@login_required
|
||||
def delete_link_from_page(page_id, link_id):
|
||||
"""Delete a link from a page"""
|
||||
try:
|
||||
success = link_manager.delete_link(page_id, link_id)
|
||||
|
||||
if success:
|
||||
return jsonify({'success': True})
|
||||
else:
|
||||
return jsonify({'error': 'Page or link not found'}), 404
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@bp.route('/link_pages/<page_id>')
|
||||
@login_required
|
||||
def get_link_page(page_id):
|
||||
"""Get link page data"""
|
||||
page_data = link_manager.get_page(page_id)
|
||||
if page_data:
|
||||
return jsonify(page_data)
|
||||
else:
|
||||
return jsonify({'error': 'Page not found'}), 404
|
||||
Reference in New Issue
Block a user