from flask import Flask, request, jsonify, redirect, url_for, session, render_template from flask_sqlalchemy import SQLAlchemy from werkzeug.security import generate_password_hash, check_password_hash from flask_session import Session from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user import random app = Flask(__name__) app.config['SECRET_KEY'] = 'your_secret_key' # Ändere dies zu einem echten geheimen Schlüssel app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///vocab.db' app.config['SESSION_TYPE'] = 'filesystem' app.config['SESSION_PERMANENT'] = False app.config['SESSION_USE_SIGNER'] = True db = SQLAlchemy(app) Session(app) login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'login' # Models class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(150), unique=True, nullable=False) password = db.Column(db.String(150), nullable=False) vocabularies = db.relationship('Vocabulary', backref='owner', lazy=True) class Vocabulary(db.Model): id = db.Column(db.Integer, primary_key=True) english = db.Column(db.String(100), nullable=False) german = db.Column(db.String(100), nullable=False) level = db.Column(db.Integer, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) def get_random_vocab(user_id): vocab_list = Vocabulary.query.filter_by(user_id=user_id).all() if not vocab_list: return None # Weight levels: Level 1 should be most common, Level 5 the least weighted_vocab_list = [] for vocab in vocab_list: weight = max(1, 6 - vocab.level) # Weight 5 for level 1, 4 for level 2, ..., 1 for level 5 weighted_vocab_list.extend([vocab] * weight) return random.choice(weighted_vocab_list) @app.route('/get_random_vocab', methods=['GET']) @login_required def get_random_vocab_route(): vocab = get_random_vocab(current_user.id) if vocab: return jsonify({ 'english': vocab.english, 'german': vocab.german, 'level': vocab.level, 'id': vocab.id, }), 200 return jsonify({'error': 'No vocabulary found'}), 404 @app.route('/update_vocab_level/', methods=['POST']) @login_required def update_vocab_level(id): vocab = Vocabulary.query.get(id) if vocab and vocab.user_id == current_user.id: if vocab.level < 5: vocab.level += 1 db.session.commit() return jsonify({'success': True}), 200 return jsonify({'message': 'Max level reached'}), 200 return jsonify({'error': 'Not found or unauthorized'}), 404 @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) @app.route('/') def index(): return render_template('start.html') @app.route('/train') @login_required def train(): return render_template('train.html') @app.route('/settings') @login_required def settings(): return render_template('settings.html') @app.route('/vocab') @login_required def vocab(): return render_template('vocab.html') @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') if not username or not password: return render_template('register.html', error='Username and password are required'), 400 existing_user = User.query.filter_by(username=username).first() if existing_user: return render_template('register.html', error='Username already taken'), 409 # 409 Conflict hashed_password = generate_password_hash(password, method='pbkdf2:sha256') new_user = User(username=username, password=hashed_password) db.session.add(new_user) db.session.commit() return redirect(url_for('login')) return render_template('register.html') @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form.get('username') password = request.form.get('password') user = User.query.filter_by(username=username).first() if user and check_password_hash(user.password, password): login_user(user) return jsonify({'success': True}), 200 else: return jsonify({'error': 'Invalid credentials'}), 401 # GET request: render login page return render_template('login.html') @app.route('/logout', methods=['POST']) @login_required def logout(): logout_user() return redirect(url_for('index')) @app.route('/add_vocab', methods=['POST']) @login_required def add_vocab(): english = request.form.get('english') german = request.form.get('german') level = int(request.form.get('level', 1)) if not english or not german or not level: return jsonify({'error': 'All fields are required'}), 400 vocab = Vocabulary(english=english, german=german, level=level, user_id=current_user.id) try: db.session.add(vocab) db.session.commit() return jsonify({'success': True}), 201 except Exception as e: db.session.rollback() return jsonify({'error': str(e)}), 500 @app.route('/update_vocab/', methods=['PUT']) @login_required def update_vocab(id): vocab = Vocabulary.query.get(id) if not vocab or vocab.user_id != current_user.id: return jsonify({'error': 'Not found or unauthorized'}), 404 english = request.json.get('english') german = request.json.get('german') level = request.json.get('level') if english: vocab.english = english if german: vocab.german = german if level: vocab.level = level try: db.session.commit() return jsonify({'success': True}), 200 except Exception as e: db.session.rollback() return jsonify({'error': str(e)}), 500 @app.route('/delete_vocab/', methods=['DELETE']) @login_required def delete_vocab(id): vocab = Vocabulary.query.get(id) if not vocab or vocab.user_id != current_user.id: return jsonify({'error': 'Not found or unauthorized'}), 404 try: db.session.delete(vocab) db.session.commit() return jsonify({'success': True}), 200 except Exception as e: db.session.rollback() return jsonify({'error': str(e)}), 500 @app.route('/get_vocab', methods=['GET']) @login_required def get_vocab(): vocab_list = Vocabulary.query.filter_by(user_id=current_user.id).all() result = [{'id': v.id, 'english': v.english, 'german': v.german, 'level': v.level} for v in vocab_list] return jsonify(result) @app.route('/change_username', methods=['POST']) @login_required def change_username(): new_username = request.form.get('new_username') if not new_username: return jsonify({'error': 'Benutzername ist erforderlich'}), 400 if User.query.filter_by(username=new_username).first(): return jsonify({'error': 'Benutzername bereits vergeben'}), 409 current_user.username = new_username try: db.session.commit() return jsonify({'success': True}), 200 except Exception as e: db.session.rollback() return jsonify({'error': str(e)}), 500 if __name__ == '__main__': with app.app_context(): db.create_all() app.run(debug=True)