Files
google-labs-jules[bot] 6f811d2028 ✨ FEATURE: Implemented User Account, Watch History, and Watchlist System (#14)
This major update transforms the platform into a personalized anime experience.

Key Changes:
- Database: Added 'users', 'watch_history', and 'watchlists' tables with appropriate relationships and indices.
- Backend: Created 'blueprints/user.py' for authentication (Register/Login/Logout) and User Data API (History/Watchlist).
- Security: Implemented password hashing using werkzeug.security and enabled Flask sessions.
- Frontend Architecture: Refactored all templates to use a new 'base.html' for global navigation and consistent styling.
- UI/UX: Added 'Continue Watching' and 'My Watchlist' sections to the home page.
- Tracking: Integrated real-time watch progress tracking in the video player.

This moves the platform from a static database to a dynamic, user-centric streaming site.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2026-01-16 07:45:49 +00:00

107 lines
3.2 KiB
Python

from flask import Blueprint, request, jsonify, session
from werkzeug.security import generate_password_hash, check_password_hash
import db
user_bp = Blueprint('user', __name__)
@user_bp.route("/api/auth/register", methods=["POST"])
def register():
data = request.get_json()
username = data.get("username")
email = data.get("email")
password = data.get("password")
if not username or not email or not password:
return jsonify({"error": "Missing fields"}), 400
if db.get_user_by_username(username):
return jsonify({"error": "Username already exists"}), 400
password_hash = generate_password_hash(password)
user_id = db.create_user(username, email, password_hash)
if user_id:
session["user_id"] = user_id
session["username"] = username
return jsonify({"success": True, "user_id": user_id})
return jsonify({"error": "Registration failed"}), 500
@user_bp.route("/api/auth/login", methods=["POST"])
def login():
data = request.get_json()
username = data.get("username")
password = data.get("password")
user = db.get_user_by_username(username)
if user and check_password_hash(user["password_hash"], password):
session["user_id"] = user["id"]
session["username"] = user["username"]
return jsonify({"success": True})
return jsonify({"error": "Invalid credentials"}), 401
@user_bp.route("/api/auth/logout", methods=["POST"])
def logout():
session.clear()
return jsonify({"success": True})
@user_bp.route("/api/auth/me", methods=["GET"])
def me():
if "user_id" in session:
return jsonify({
"logged_in": True,
"user_id": session["user_id"],
"username": session["username"]
})
return jsonify({"logged_in": False})
@user_bp.route("/api/user/history", methods=["GET", "POST"])
def history():
if "user_id" not in session:
return jsonify({"error": "Unauthorized"}), 401
user_id = session["user_id"]
if request.method == "POST":
data = request.get_json()
mal_id = data.get("mal_id")
episode = data.get("episode")
progress = data.get("progress", 0)
# Get internal anime ID
anime = db.get_anime_by_mal_id(mal_id)
if not anime:
return jsonify({"error": "Anime not found"}), 404
db.update_watch_history(user_id, anime["id"], episode, progress)
return jsonify({"success": True})
else:
limit = request.args.get("limit", 10, type=int)
history_data = db.get_user_watch_history(user_id, limit)
return jsonify(history_data)
@user_bp.route("/api/user/watchlist", methods=["GET", "POST"])
def watchlist():
if "user_id" not in session:
return jsonify({"error": "Unauthorized"}), 401
user_id = session["user_id"]
if request.method == "POST":
data = request.get_json()
mal_id = data.get("mal_id")
status = data.get("status")
anime = db.get_anime_by_mal_id(mal_id)
if not anime:
return jsonify({"error": "Anime not found"}), 404
db.update_watchlist(user_id, anime["id"], status)
return jsonify({"success": True})
else:
watchlist_data = db.get_user_watchlist(user_id)
return jsonify(watchlist_data)