added
This commit is contained in:
+228
@@ -0,0 +1,228 @@
|
||||
|
||||
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)
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.manga-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.manga-card {
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.manga-card img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
Reference in New Issue
Block a user