detector-ai / app_full.py
Slovand's picture
Update app_full.py
b745c2e verified
# app_full.py - COMPLETE VERSION WITH OPTIMIZATION & COMPARE ENDPOINT
from flask import Flask, render_template, request, jsonify, session, redirect
from flask_cors import CORS
import os
import uuid
from werkzeug.utils import secure_filename
from detector import AIDetector
from database import Database
from auth import auth_bp
from datetime import datetime
import nltk
# Download NLTK data
try:
nltk.data.find('tokenizers/punkt')
except LookupError:
nltk.download('punkt')
nltk.download('stopwords')
app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY', 'dtector-ai-secret-key-2026-production')
CORS(app)
# Register blueprint
app.register_blueprint(auth_bp)
# Config
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
app.config['UPLOAD_FOLDER'] = 'uploads'
ALLOWED_EXTENSIONS = {'pdf', 'txt', 'docx'}
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
detector = AIDetector()
db = Database()
# Optional: Load RoBERTa detector if available
try:
from detector_roberta import RoBERTaDetector
roberta_detector = RoBERTaDetector()
ROBERTA_AVAILABLE = True
except:
ROBERTA_AVAILABLE = False
print("⚠️ RoBERTa detector not available")
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def get_current_user():
user_id = session.get('user_id')
if not user_id:
return None
return {'id': user_id, 'username': session.get('username')}
# ============ PAGE ROUTES ============
@app.route('/')
def splash():
return render_template('splash.html')
@app.route('/landing')
def landing():
return render_template('landing.html')
@app.route('/login')
def login_page():
return render_template('login.html')
@app.route('/register')
def register_page():
return render_template('register.html')
@app.route('/verify')
def verify_page():
user_id = request.args.get('user_id') or session.get('pending_user_id')
return render_template('verify.html', user_id=user_id)
@app.route('/dashboard')
def dashboard():
return render_template('dashboard.html')
@app.route('/profile')
def profile_page():
if not session.get('user_id'):
return redirect('/login')
return render_template('profile.html')
@app.route('/change-password')
def change_password_page():
if not session.get('user_id'):
return redirect('/login')
return render_template('change_password.html')
# ============ API ROUTES ============
@app.route('/api/detect/text', methods=['POST'])
def detect_text():
data = request.get_json()
text = data.get('text', '')
model = data.get('model', 'indobert')
user = get_current_user()
if not text:
return jsonify({'error': 'Text is required'}), 400
# Pilih model
if model == 'roberta' and ROBERTA_AVAILABLE:
result = roberta_detector.detect(text)
else:
result = detector.detect(text)
# Simpan history hanya jika user login
if not result.get('error') and user:
db.add_detection(
text, result,
user_id=user['id'] if user else None,
file_name=None,
file_type='text'
)
return jsonify(result)
@app.route('/api/detect/file', methods=['POST'])
def detect_file():
if 'file' not in request.files:
return jsonify({'error': 'No file uploaded'}), 400
file = request.files['file']
model = request.form.get('model', 'indobert')
user = get_current_user()
if file.filename == '':
return jsonify({'error': 'Empty filename'}), 400
if not allowed_file(file.filename):
return jsonify({'error': 'File type not allowed'}), 400
filename = secure_filename(file.filename)
unique_filename = f"{uuid.uuid4().hex}_{filename}"
filepath = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)
file.save(filepath)
try:
file_ext = filename.rsplit('.', 1)[1].lower()
if model == 'roberta' and ROBERTA_AVAILABLE:
result = roberta_detector.detect_file(filepath, file_ext)
else:
result = detector.detect_file(filepath, file_ext)
# Simpan history hanya jika user login
if not result.get('error') and user:
text = result.get('preview', '')
db.add_detection(
text, result,
user_id=user['id'] if user else None,
file_name=filename,
file_type=file_ext
)
return jsonify(result)
except Exception as e:
return jsonify({'error': str(e)}), 500
finally:
if os.path.exists(filepath):
os.remove(filepath)
@app.route('/api/compare', methods=['POST'])
def compare_models():
"""Endpoint untuk membandingkan IndoBERT dan RoBERTa secara langsung"""
data = request.get_json()
text = data.get('text', '')
if not text:
return jsonify({'error': 'Text is required'}), 400
result = {
'indobert': detector.detect(text),
'roberta': None
}
if ROBERTA_AVAILABLE:
result['roberta'] = roberta_detector.detect(text)
else:
result['roberta'] = {'error': 'RoBERTa model not available'}
return jsonify(result)
@app.route('/api/history', methods=['GET'])
def get_history():
user = get_current_user()
limit = request.args.get('limit', 50, type=int)
if user:
history = db.get_user_history(user['id'], limit)
else:
return jsonify([])
result = []
for item in history:
result.append({
'id': item.id,
'text_preview': item.text_preview,
'file_name': item.file_name,
'file_type': item.file_type,
'ai_probability': item.ai_probability,
'human_probability': item.human_probability,
'confidence': item.confidence,
'is_ai': bool(item.is_ai),
'is_pinned': item.is_pinned,
'created_at': item.created_at.strftime('%Y-%m-%d %H:%M:%S')
})
return jsonify(result)
@app.route('/api/history/<int:detection_id>', methods=['DELETE'])
def delete_detection(detection_id):
user = get_current_user()
if not user:
return jsonify({'error': 'Login required'}), 401
if db.delete_detection(detection_id, user['id']):
return jsonify({'success': True})
return jsonify({'error': 'Detection not found'}), 404
@app.route('/api/history/<int:detection_id>/pin', methods=['POST'])
def toggle_pin(detection_id):
user = get_current_user()
if not user:
return jsonify({'error': 'Login required'}), 401
is_pinned = db.toggle_pin(detection_id, user['id'])
if is_pinned is not None:
return jsonify({'success': True, 'is_pinned': is_pinned})
return jsonify({'error': 'Detection not found'}), 404
@app.route('/api/stats', methods=['GET'])
def get_stats():
user = get_current_user()
if user:
stats = db.get_user_stats(user['id'])
else:
stats = {'total': 0, 'ai_count': 0, 'human_count': 0, 'avg_confidence': 0}
return jsonify(stats)
@app.route('/health', methods=['GET'])
def health():
return jsonify({
'status': 'healthy',
'model_loaded': detector.model is not None,
'roberta_available': ROBERTA_AVAILABLE,
'timestamp': datetime.now().isoformat()
})
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5001))
app.run(host='0.0.0.0', port=port)