import os from flask import Flask, request, jsonify, session, send_from_directory from flask_sqlalchemy import SQLAlchemy import os import requests app = Flask(__name__, static_folder='../frontend/build', static_url_path='/') app.config['SECRET_KEY'] = 'your_secret_key' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///manga.db' db = SQLAlchemy(app) # --- Database Models --- class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password = db.Column(db.String(120), nullable=False) class Manga(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(120), nullable=False) api_id = db.Column(db.String(120), unique=True, nullable=False) image_url = db.Column(db.String(255), nullable=True) class UserManga(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) manga_id = db.Column(db.Integer, db.ForeignKey('manga.id'), nullable=False) volume_number = db.Column(db.Integer, nullable=True) # New field for volume number class Friend(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) friend_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) # --- API Routes --- @app.route('/api/signup', methods=['POST']) def signup(): data = request.get_json() username = data.get('username') password = data.get('password') if not username or not password: return jsonify({'message': 'Username and password are required'}), 400 if User.query.filter_by(username=username).first(): return jsonify({'message': 'Username already exists'}), 409 new_user = User(username=username, password=password) # In a real app, hash passwords! db.session.add(new_user) db.session.commit() return jsonify({'message': 'User created successfully'}), 201 @app.route('/api/login', methods=['POST']) def login(): data = request.get_json() username = data.get('username') password = data.get('password') user = User.query.filter_by(username=username, password=password).first() # In a real app, check hashed password if user: session['user_id'] = user.id return jsonify({'message': 'Login successful', 'user_id': user.id}), 200 return jsonify({'message': 'Invalid credentials'}), 401 @app.route('/api/logout') def logout(): session.pop('user_id', None) return jsonify({'message': 'Logged out successfully'}), 200 @app.route('/api/dashboard') def dashboard(): if 'user_id' not in session: return jsonify({'message': 'Unauthorized'}), 401 user = User.query.get(session['user_id']) if not user: return jsonify({'message': 'User not found'}), 404 user_mangas = UserManga.query.filter_by(user_id=user.id).all() grouped_user_mangas = {} for um in user_mangas: manga = Manga.query.get(um.manga_id) if manga: if manga.title not in grouped_user_mangas: grouped_user_mangas[manga.title] = { 'manga_details': { 'id': manga.id, 'title': manga.title, 'api_id': manga.api_id, 'image_url': manga.image_url }, 'volumes': [] } grouped_user_mangas[manga.title]['volumes'].append(um.volume_number) grouped_user_mangas[manga.title]['volumes'].sort() friends = Friend.query.filter_by(user_id=user.id).all() friend_users = [] for f in friends: friend_user = User.query.get(f.friend_id) if friend_user: friend_users.append({'id': friend_user.id, 'username': friend_user.username}) friend_mangas_data = {} for friend_user_data in friend_users: friend_id = friend_user_data['id'] friend_username = friend_user_data['username'] friend_user_mangas = UserManga.query.filter_by(user_id=friend_id).all() grouped_friend_mangas = {} for fum in friend_user_mangas: fmanga = Manga.query.get(fum.manga_id) if fmanga: if fmanga.title not in grouped_friend_mangas: grouped_friend_mangas[fmanga.title] = { 'manga_details': { 'id': fmanga.id, 'title': fmanga.title, 'api_id': fmanga.api_id, 'image_url': fmanga.image_url }, 'volumes': [] } grouped_friend_mangas[fmanga.title]['volumes'].append(fum.volume_number) grouped_friend_mangas[fmanga.title]['volumes'].sort() friend_mangas_data[friend_username] = grouped_friend_mangas return jsonify({ 'user': {'id': user.id, 'username': user.username}, 'mangas': grouped_user_mangas, 'friends': friend_users, 'friend_mangas': friend_mangas_data }), 200 @app.route('/api/search', methods=['POST']) def search(): if 'user_id' not in session: return jsonify({'message': 'Unauthorized'}), 401 data = request.get_json() manga_title = data.get('query') if not manga_title: return jsonify({'message': 'Query parameter is required'}), 400 response = requests.get(f'https://api.jikan.moe/v4/manga?q={manga_title}') manga_data = response.json() return jsonify(manga_data), 200 @app.route('/api/add_manga', methods=['POST']) def add_manga(): if 'user_id' not in session: return jsonify({'message': 'Unauthorized'}), 401 data = request.get_json() manga_title = data.get('manga_title') manga_api_id = data.get('manga_api_id') image_url = data.get('image_url') volume_number = data.get('volume_number') if not manga_title or not manga_api_id: return jsonify({'message': 'Manga title and API ID are required'}), 400 manga = Manga.query.filter_by(api_id=manga_api_id).first() if not manga: manga = Manga(title=manga_title, api_id=manga_api_id, image_url=image_url) db.session.add(manga) db.session.commit() user_manga = UserManga.query.filter_by( user_id=session['user_id'], manga_id=manga.id, volume_number=volume_number ).first() if not user_manga: user_manga = UserManga(user_id=session['user_id'], manga_id=manga.id, volume_number=volume_number) db.session.add(user_manga) db.session.commit() return jsonify({'message': 'Manga added successfully'}), 201 @app.route('/api/search_user', methods=['POST']) def search_user(): if 'user_id' not in session: return jsonify({'message': 'Unauthorized'}), 401 data = request.get_json() username = data.get('query') if not username: return jsonify({'message': 'Query parameter is required'}), 400 users = User.query.filter(User.username.like(f'%{username}%')).all() users_data = [{'id': user.id, 'username': user.username} for user in users] return jsonify({'users': users_data}), 200 @app.route('/api/add_friend', methods=['POST']) def add_friend(): if 'user_id' not in session: return jsonify({'message': 'Unauthorized'}), 401 data = request.get_json() friend_id = data.get('friend_id') if not friend_id: return jsonify({'message': 'Friend ID is required'}), 400 friendship = Friend.query.filter_by(user_id=session['user_id'], friend_id=friend_id).first() if not friendship: new_friend = Friend(user_id=session['user_id'], friend_id=friend_id) db.session.add(new_friend) db.session.commit() return jsonify({'message': 'Friend added successfully'}), 201 @app.route('/') def serve_index(): return send_from_directory(app.static_folder, 'index.html') @app.errorhandler(404) def not_found(e): return send_from_directory(app.static_folder, 'index.html') if __name__ == '__main__': with app.app_context(): db.create_all() app.run(debug=True)