updated first commit
This commit is contained in:
153
app/routes/api.py
Normal file
153
app/routes/api.py
Normal file
@@ -0,0 +1,153 @@
|
||||
"""
|
||||
API routes for player clients
|
||||
"""
|
||||
|
||||
from flask import Blueprint, request, jsonify, url_for
|
||||
from app.models.player import Player
|
||||
from app.models.content import Content
|
||||
from app.extensions import bcrypt, db
|
||||
|
||||
bp = Blueprint('api', __name__)
|
||||
|
||||
@bp.route('/playlists', methods=['GET'])
|
||||
def get_playlists():
|
||||
"""Get playlist for a player"""
|
||||
hostname = request.args.get('hostname')
|
||||
quickconnect_code = request.args.get('quickconnect_code')
|
||||
|
||||
# Validate parameters
|
||||
if not hostname or not quickconnect_code:
|
||||
return jsonify({'error': 'Hostname and quick connect code are required'}), 400
|
||||
|
||||
# Find player and verify credentials
|
||||
player = Player.query.filter_by(hostname=hostname).first()
|
||||
if not player or not player.verify_quickconnect_code(quickconnect_code):
|
||||
return jsonify({'error': 'Invalid hostname or quick connect code'}), 404
|
||||
|
||||
# Update last seen
|
||||
player.last_seen = db.func.current_timestamp()
|
||||
db.session.commit()
|
||||
|
||||
# Get content based on player's group status
|
||||
if player.is_locked_to_group:
|
||||
# Player is locked to a group - get shared content
|
||||
group = player.locked_to_group
|
||||
player_ids = [p.id for p in group.players]
|
||||
|
||||
# Get unique content by filename (first occurrence)
|
||||
content_query = (
|
||||
db.session.query(
|
||||
Content.file_name,
|
||||
db.func.min(Content.id).label('id'),
|
||||
db.func.min(Content.duration).label('duration'),
|
||||
db.func.min(Content.position).label('position'),
|
||||
db.func.min(Content.content_type).label('content_type')
|
||||
)
|
||||
.filter(Content.player_id.in_(player_ids))
|
||||
.group_by(Content.file_name)
|
||||
)
|
||||
|
||||
content = db.session.query(Content).filter(
|
||||
Content.id.in_([c.id for c in content_query])
|
||||
).order_by(Content.position).all()
|
||||
else:
|
||||
# Individual player content
|
||||
content = Content.query.filter_by(player_id=player.id).order_by(Content.position).all()
|
||||
|
||||
# Build playlist
|
||||
playlist = []
|
||||
for media in content:
|
||||
playlist.append({
|
||||
'file_name': media.file_name,
|
||||
'url': url_for('content.media', filename=media.file_name, _external=True),
|
||||
'duration': media.duration,
|
||||
'content_type': media.content_type,
|
||||
'position': media.position
|
||||
})
|
||||
|
||||
return jsonify({
|
||||
'playlist': playlist,
|
||||
'playlist_version': player.playlist_version,
|
||||
'hashed_quickconnect': player.quickconnect_password,
|
||||
'player_id': player.id,
|
||||
'player_name': player.username
|
||||
})
|
||||
|
||||
@bp.route('/playlist_version', methods=['GET'])
|
||||
def get_playlist_version():
|
||||
"""Get playlist version for a player (for checking updates)"""
|
||||
hostname = request.args.get('hostname')
|
||||
quickconnect_code = request.args.get('quickconnect_code')
|
||||
|
||||
# Validate parameters
|
||||
if not hostname or not quickconnect_code:
|
||||
return jsonify({'error': 'Hostname and quick connect code are required'}), 400
|
||||
|
||||
# Find player and verify credentials
|
||||
player = Player.query.filter_by(hostname=hostname).first()
|
||||
if not player or not player.verify_quickconnect_code(quickconnect_code):
|
||||
return jsonify({'error': 'Invalid hostname or quick connect code'}), 404
|
||||
|
||||
# Update last seen
|
||||
player.last_seen = db.func.current_timestamp()
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({
|
||||
'playlist_version': player.playlist_version,
|
||||
'hashed_quickconnect': player.quickconnect_password
|
||||
})
|
||||
|
||||
@bp.route('/player_status', methods=['POST'])
|
||||
def update_player_status():
|
||||
"""Update player status (heartbeat)"""
|
||||
data = request.get_json()
|
||||
|
||||
if not data:
|
||||
return jsonify({'error': 'JSON data required'}), 400
|
||||
|
||||
hostname = data.get('hostname')
|
||||
quickconnect_code = data.get('quickconnect_code')
|
||||
|
||||
if not hostname or not quickconnect_code:
|
||||
return jsonify({'error': 'Hostname and quick connect code are required'}), 400
|
||||
|
||||
# Find player and verify credentials
|
||||
player = Player.query.filter_by(hostname=hostname).first()
|
||||
if not player or not player.verify_quickconnect_code(quickconnect_code):
|
||||
return jsonify({'error': 'Invalid hostname or quick connect code'}), 404
|
||||
|
||||
# Update player status
|
||||
player.last_seen = db.func.current_timestamp()
|
||||
player.is_active = True
|
||||
|
||||
# Optional: Update additional status info if provided
|
||||
if 'status' in data:
|
||||
# Could store additional status information in the future
|
||||
pass
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'playlist_version': player.playlist_version,
|
||||
'message': 'Status updated successfully'
|
||||
})
|
||||
|
||||
@bp.route('/health', methods=['GET'])
|
||||
def health_check():
|
||||
"""Health check endpoint"""
|
||||
return jsonify({
|
||||
'status': 'healthy',
|
||||
'service': 'SKE Digital Signage Server',
|
||||
'version': '2.0.0'
|
||||
})
|
||||
|
||||
@bp.errorhandler(404)
|
||||
def api_not_found(error):
|
||||
"""API 404 handler"""
|
||||
return jsonify({'error': 'API endpoint not found'}), 404
|
||||
|
||||
@bp.errorhandler(500)
|
||||
def api_internal_error(error):
|
||||
"""API 500 handler"""
|
||||
return jsonify({'error': 'Internal server error'}), 500
|
||||
Reference in New Issue
Block a user