Spaces:
Runtime error
Runtime error
Upload 12 files
Browse files- .gitattributes +1 -0
- admin.py +121 -0
- app.py +205 -27
- instance/chats.db +0 -0
- models.py +1 -0
- requirements.txt +16 -14
.gitattributes
CHANGED
@@ -1,2 +1,3 @@
|
|
1 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
2 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
|
|
|
1 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
2 |
*.pth filter=lfs diff=lfs merge=lfs -text
|
3 |
+
instance/chats.db filter=lfs diff=lfs merge=lfs -text
|
admin.py
ADDED
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Blueprint, render_template, jsonify, request, flash, redirect, url_for
|
2 |
+
from flask_login import login_required, current_user
|
3 |
+
from models import User, Chat, AnalysisReport
|
4 |
+
from extensions import db
|
5 |
+
from datetime import datetime, timedelta
|
6 |
+
from sqlalchemy import func
|
7 |
+
|
8 |
+
admin_bp = Blueprint('admin_bp', __name__, template_folder='templates')
|
9 |
+
|
10 |
+
|
11 |
+
@admin_bp.before_request
|
12 |
+
@login_required
|
13 |
+
def restrict_admin_panel():
|
14 |
+
if not current_user.is_admin:
|
15 |
+
flash('Доступ запрещен', 'danger')
|
16 |
+
return redirect(url_for('index'))
|
17 |
+
|
18 |
+
|
19 |
+
@admin_bp.route('/')
|
20 |
+
def dashboard():
|
21 |
+
# Статистика за последние 30 дней
|
22 |
+
end_date = datetime.now()
|
23 |
+
start_date = end_date - timedelta(days=30)
|
24 |
+
|
25 |
+
# Основная статистика
|
26 |
+
users_count = User.query.count()
|
27 |
+
new_users = User.query.filter(User.created_at >= start_date).count()
|
28 |
+
reports_count = AnalysisReport.query.count()
|
29 |
+
active_users = db.session.query(Chat.user_id).distinct().count()
|
30 |
+
|
31 |
+
# Статистика по эмоциям
|
32 |
+
emotion_stats = db.session.query(
|
33 |
+
AnalysisReport.emotion,
|
34 |
+
func.count(AnalysisReport.id).label('count')
|
35 |
+
).group_by(AnalysisReport.emotion).all()
|
36 |
+
|
37 |
+
# Активность пользователей
|
38 |
+
user_activity = db.session.query(
|
39 |
+
User.username,
|
40 |
+
func.count(AnalysisReport.id).label('report_count')
|
41 |
+
).join(
|
42 |
+
AnalysisReport, User.id == AnalysisReport.user_id
|
43 |
+
).group_by(
|
44 |
+
User.username
|
45 |
+
).order_by(
|
46 |
+
func.count(AnalysisReport.id).desc()
|
47 |
+
).limit(10).all()
|
48 |
+
|
49 |
+
return render_template('admin/dashboard.html',
|
50 |
+
users_count=users_count,
|
51 |
+
new_users=new_users,
|
52 |
+
reports_count=reports_count,
|
53 |
+
active_users=active_users,
|
54 |
+
emotion_stats=emotion_stats,
|
55 |
+
user_activity=user_activity)
|
56 |
+
|
57 |
+
|
58 |
+
@admin_bp.route('/users')
|
59 |
+
def manage_users():
|
60 |
+
search_query = request.args.get('search', '')
|
61 |
+
page = request.args.get('page', 1, type=int)
|
62 |
+
|
63 |
+
query = User.query.order_by(User.created_at.desc())
|
64 |
+
|
65 |
+
if search_query:
|
66 |
+
query = query.filter(User.username.ilike(f'%{search_query}%') |
|
67 |
+
User.email.ilike(f'%{search_query}%'))
|
68 |
+
|
69 |
+
users = query.paginate(page=page, per_page=20, error_out=False)
|
70 |
+
|
71 |
+
return render_template('admin/users.html',
|
72 |
+
users=users,
|
73 |
+
search_query=search_query)
|
74 |
+
|
75 |
+
|
76 |
+
@admin_bp.route('/reports')
|
77 |
+
def view_reports():
|
78 |
+
emotion_filter = request.args.get('emotion')
|
79 |
+
page = request.args.get('page', 1, type=int)
|
80 |
+
|
81 |
+
query = AnalysisReport.query.order_by(AnalysisReport.created_at.desc())
|
82 |
+
|
83 |
+
if emotion_filter:
|
84 |
+
query = query.filter(AnalysisReport.emotion == emotion_filter)
|
85 |
+
|
86 |
+
reports = query.paginate(page=page, per_page=50, error_out=False)
|
87 |
+
|
88 |
+
# Получаем список всех эмоций для фильтра
|
89 |
+
emotions = db.session.query(
|
90 |
+
AnalysisReport.emotion.distinct().label('emotion')
|
91 |
+
).all()
|
92 |
+
|
93 |
+
return render_template('admin/reports.html',
|
94 |
+
reports=reports,
|
95 |
+
emotions=emotions,
|
96 |
+
current_emotion=emotion_filter)
|
97 |
+
|
98 |
+
|
99 |
+
@admin_bp.route('/toggle_admin/<int:user_id>', methods=['POST'])
|
100 |
+
def toggle_admin(user_id):
|
101 |
+
user = User.query.get_or_404(user_id)
|
102 |
+
user.is_admin = not user.is_admin
|
103 |
+
db.session.commit()
|
104 |
+
return jsonify({'status': 'success', 'is_admin': user.is_admin})
|
105 |
+
|
106 |
+
|
107 |
+
@admin_bp.route('/delete_user/<int:user_id>', methods=['POST'])
|
108 |
+
def delete_user(user_id):
|
109 |
+
if current_user.id == user_id:
|
110 |
+
return jsonify({'status': 'error', 'message': 'Нельзя удалить себя'}), 400
|
111 |
+
|
112 |
+
user = User.query.get_or_404(user_id)
|
113 |
+
|
114 |
+
# Удаляем все связанные данные пользователя
|
115 |
+
AnalysisReport.query.filter_by(user_id=user_id).delete()
|
116 |
+
Chat.query.filter_by(user_id=user_id).delete()
|
117 |
+
|
118 |
+
db.session.delete(user)
|
119 |
+
db.session.commit()
|
120 |
+
|
121 |
+
return jsonify({'status': 'success'})
|
app.py
CHANGED
@@ -12,7 +12,10 @@ import sqlite3
|
|
12 |
from pathlib import Path
|
13 |
import whisper
|
14 |
from extensions import db, login_manager
|
15 |
-
|
|
|
|
|
|
|
16 |
|
17 |
instance_path = Path(__file__).parent / 'instance'
|
18 |
instance_path.mkdir(exist_ok=True, mode=0o755)
|
@@ -27,7 +30,7 @@ app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
|
27 |
db.init_app(app)
|
28 |
login_manager.init_app(app)
|
29 |
login_manager.login_view = 'auth_bp.login'
|
30 |
-
|
31 |
# Инициализация моделей
|
32 |
def init_models():
|
33 |
try:
|
@@ -63,12 +66,38 @@ models = init_models()
|
|
63 |
if not models:
|
64 |
raise RuntimeError("Не удалось загрузить модели")
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
# Импорт Blueprint
|
67 |
from auth import auth_bp
|
68 |
from profile import profile_bp
|
69 |
|
70 |
app.register_blueprint(auth_bp)
|
71 |
app.register_blueprint(profile_bp)
|
|
|
72 |
|
73 |
# Делаем переменные доступными
|
74 |
emotion_map = models['emotion_map']
|
@@ -76,6 +105,21 @@ speech_to_text_model = models['speech_to_text_model']
|
|
76 |
text_classifier = models['text_classifier']
|
77 |
audio_classifier = models['audio_classifier']
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
def transcribe_audio(audio_path):
|
81 |
"""Преобразование аудио в текст с помощью Whisper"""
|
@@ -94,29 +138,12 @@ login_manager = LoginManager(app)
|
|
94 |
login_manager.login_view = 'login'
|
95 |
|
96 |
|
97 |
-
# Модель пользователя для Flask-Login
|
98 |
-
class User(UserMixin):
|
99 |
-
def __init__(self, id, username, email, password_hash):
|
100 |
-
self.id = id
|
101 |
-
self.username = username
|
102 |
-
self.email = email
|
103 |
-
self.password_hash = password_hash
|
104 |
-
|
105 |
-
def check_password(self, password):
|
106 |
-
return check_password_hash(self.password_hash, password)
|
107 |
|
108 |
|
109 |
@login_manager.user_loader
|
110 |
def load_user(user_id):
|
111 |
-
|
112 |
-
|
113 |
-
"SELECT id, username, email, password_hash FROM users WHERE id = ?",
|
114 |
-
(user_id,)
|
115 |
-
).fetchone()
|
116 |
-
conn.close()
|
117 |
-
if user:
|
118 |
-
return User(id=user['id'], username=user['username'], email=user['email'], password_hash=user['password_hash'])
|
119 |
-
return None
|
120 |
|
121 |
|
122 |
# Инициализация БД
|
@@ -256,6 +283,46 @@ def index():
|
|
256 |
conn.close()
|
257 |
|
258 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
@app.route("/analyze", methods=["POST"])
|
260 |
@login_required
|
261 |
def analyze_text():
|
@@ -356,13 +423,80 @@ def analyze_audio():
|
|
356 |
return jsonify({'error': str(e)}), 500
|
357 |
|
358 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
359 |
@app.route('/get_chats')
|
360 |
@login_required
|
361 |
def get_chats():
|
362 |
conn = get_db_connection()
|
363 |
try:
|
364 |
chats = conn.execute(
|
365 |
-
"SELECT chat_id, title FROM chats WHERE user_id = ? ORDER BY created_at DESC",
|
366 |
(current_user.id,)
|
367 |
).fetchall()
|
368 |
return jsonify([dict(chat) for chat in chats])
|
@@ -373,21 +507,60 @@ def get_chats():
|
|
373 |
@app.route('/start_chat', methods=['POST'])
|
374 |
@login_required
|
375 |
def start_chat():
|
376 |
-
conn = get_db_connection()
|
377 |
try:
|
378 |
chat_id = str(uuid.uuid4())
|
|
|
|
|
|
|
379 |
conn.execute(
|
380 |
-
"INSERT INTO chats (chat_id, user_id,
|
381 |
-
(chat_id, current_user.id,
|
382 |
)
|
383 |
conn.commit()
|
384 |
-
|
|
|
|
|
|
|
|
|
|
|
385 |
except Exception as e:
|
386 |
return jsonify({"error": str(e)}), 500
|
387 |
finally:
|
388 |
conn.close()
|
389 |
|
390 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
@app.route('/load_chat/<chat_id>')
|
392 |
@login_required
|
393 |
def load_chat(chat_id):
|
@@ -471,5 +644,10 @@ def save_message():
|
|
471 |
finally:
|
472 |
conn.close()
|
473 |
|
|
|
|
|
|
|
474 |
if __name__ == "__main__":
|
475 |
-
app.run(debug=True)
|
|
|
|
|
|
12 |
from pathlib import Path
|
13 |
import whisper
|
14 |
from extensions import db, login_manager
|
15 |
+
import json
|
16 |
+
from admin import admin_bp
|
17 |
+
from flask_migrate import Migrate
|
18 |
+
from models import User
|
19 |
|
20 |
instance_path = Path(__file__).parent / 'instance'
|
21 |
instance_path.mkdir(exist_ok=True, mode=0o755)
|
|
|
30 |
db.init_app(app)
|
31 |
login_manager.init_app(app)
|
32 |
login_manager.login_view = 'auth_bp.login'
|
33 |
+
migrate = Migrate(app, db)
|
34 |
# Инициализация моделей
|
35 |
def init_models():
|
36 |
try:
|
|
|
66 |
if not models:
|
67 |
raise RuntimeError("Не удалось загрузить модели")
|
68 |
|
69 |
+
|
70 |
+
@app.template_filter('datetimeformat')
|
71 |
+
def datetimeformat(value, format='%d.%m.%Y %H:%M'):
|
72 |
+
if value is None:
|
73 |
+
return ""
|
74 |
+
return value.strftime(format)
|
75 |
+
|
76 |
+
@app.context_processor
|
77 |
+
def utility_processor():
|
78 |
+
return {
|
79 |
+
'emotion_map': {
|
80 |
+
'joy': '😊 Радость',
|
81 |
+
'neutral': '😐 Нейтрально',
|
82 |
+
'anger': '😠 Злость',
|
83 |
+
'sadness': '😢 Грусть',
|
84 |
+
'surprise': '😲 Удивление'
|
85 |
+
},
|
86 |
+
'get_emotion_color': lambda emotion: {
|
87 |
+
'joy': '#00b894',
|
88 |
+
'neutral': '#636e72',
|
89 |
+
'anger': '#d63031',
|
90 |
+
'sadness': '#0984e3',
|
91 |
+
'surprise': '#fdcb6e'
|
92 |
+
}.get(emotion, '#4a4ae8')
|
93 |
+
}
|
94 |
# Импорт Blueprint
|
95 |
from auth import auth_bp
|
96 |
from profile import profile_bp
|
97 |
|
98 |
app.register_blueprint(auth_bp)
|
99 |
app.register_blueprint(profile_bp)
|
100 |
+
app.register_blueprint(admin_bp, url_prefix='/admin')
|
101 |
|
102 |
# Делаем переменные доступными
|
103 |
emotion_map = models['emotion_map']
|
|
|
105 |
text_classifier = models['text_classifier']
|
106 |
audio_classifier = models['audio_classifier']
|
107 |
|
108 |
+
@app.cli.command('create-admin')
|
109 |
+
def create_admin():
|
110 |
+
"""Создание администратора"""
|
111 |
+
email = input("Введите email: ")
|
112 |
+
password = input("Введите пароль: ")
|
113 |
+
user = User.query.filter_by(email=email).first()
|
114 |
+
if user:
|
115 |
+
user.is_admin = True
|
116 |
+
user.set_password(password)
|
117 |
+
else:
|
118 |
+
user = User(email=email, username=email, is_admin=True)
|
119 |
+
user.set_password(password)
|
120 |
+
db.session.add(user)
|
121 |
+
db.session.commit()
|
122 |
+
print(f"Администратор {email} создан")
|
123 |
|
124 |
def transcribe_audio(audio_path):
|
125 |
"""Преобразование аудио в текст с помощью Whisper"""
|
|
|
138 |
login_manager.login_view = 'login'
|
139 |
|
140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
|
142 |
|
143 |
@login_manager.user_loader
|
144 |
def load_user(user_id):
|
145 |
+
from models import User
|
146 |
+
return User.query.get(int(user_id))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
|
149 |
# Инициализация БД
|
|
|
283 |
conn.close()
|
284 |
|
285 |
|
286 |
+
@app.route('/profile')
|
287 |
+
@login_required
|
288 |
+
def profile():
|
289 |
+
conn = get_db_connection()
|
290 |
+
try:
|
291 |
+
# Запрашиваем все анализы пользователя
|
292 |
+
reports = conn.execute(
|
293 |
+
"SELECT * FROM analysis_reports WHERE user_id = ? ORDER BY created_at DESC",
|
294 |
+
(current_user.id,)
|
295 |
+
).fetchall()
|
296 |
+
|
297 |
+
# Статистика: общее количество анализов
|
298 |
+
total_reports = len(reports)
|
299 |
+
|
300 |
+
# Статистика: самая частая эмоция
|
301 |
+
emotion_counts = {}
|
302 |
+
for r in reports:
|
303 |
+
emotion_counts[r['emotion']] = emotion_counts.get(r['emotion'], 0) + 1
|
304 |
+
|
305 |
+
most_common_emotion = max(emotion_counts, key=emotion_counts.get) if emotion_counts else None
|
306 |
+
|
307 |
+
return render_template(
|
308 |
+
"profile.html",
|
309 |
+
reports=reports,
|
310 |
+
total_reports=total_reports,
|
311 |
+
most_common_emotion=most_common_emotion,
|
312 |
+
emotion_map={
|
313 |
+
'joy': '😊 Радость',
|
314 |
+
'neutral': '😐 Нейтрально',
|
315 |
+
'anger': '😠 Злость',
|
316 |
+
'sadness': '😢 Грусть',
|
317 |
+
'surprise': '😲 Удивление'
|
318 |
+
}
|
319 |
+
)
|
320 |
+
except Exception as e:
|
321 |
+
flash(f"Ошибка загрузки данных: {e}", "danger")
|
322 |
+
return redirect(url_for('index'))
|
323 |
+
finally:
|
324 |
+
conn.close()
|
325 |
+
|
326 |
@app.route("/analyze", methods=["POST"])
|
327 |
@login_required
|
328 |
def analyze_text():
|
|
|
423 |
return jsonify({'error': str(e)}), 500
|
424 |
|
425 |
|
426 |
+
|
427 |
+
|
428 |
+
|
429 |
+
@app.route('/analyze_telegram_chat', methods=['POST'])
|
430 |
+
@login_required
|
431 |
+
def analyze_telegram_chat():
|
432 |
+
if 'file' not in request.files:
|
433 |
+
return jsonify({'error': 'No file uploaded'}), 400
|
434 |
+
file = request.files['file']
|
435 |
+
if file.filename.split('.')[-1].lower() != 'json':
|
436 |
+
return jsonify({'error': 'Invalid file format. Only JSON allowed'}), 400
|
437 |
+
try:
|
438 |
+
data = json.load(file)
|
439 |
+
|
440 |
+
messages = []
|
441 |
+
for msg in data.get('messages', []):
|
442 |
+
text = msg.get('text')
|
443 |
+
sender = msg.get('from') or msg.get('sender') or 'Неизвестный пользователь'
|
444 |
+
if isinstance(text, str) and len(text.strip()) > 5:
|
445 |
+
messages.append({
|
446 |
+
'text': text,
|
447 |
+
'timestamp': msg.get('date', datetime.now().isoformat()),
|
448 |
+
'from': sender # <-- сохраняем имя отправителя
|
449 |
+
})
|
450 |
+
|
451 |
+
if not messages:
|
452 |
+
return jsonify({'error': 'No valid text messages found'}), 400
|
453 |
+
|
454 |
+
results = []
|
455 |
+
for msg in messages[:500]:
|
456 |
+
prediction = text_classifier(msg['text'])[0]
|
457 |
+
results.append({
|
458 |
+
'text': msg['text'],
|
459 |
+
'emotion': prediction['label'],
|
460 |
+
'confidence': prediction['score'],
|
461 |
+
'timestamp': msg['timestamp'],
|
462 |
+
'from': msg['from'] # <-- передаем дальше
|
463 |
+
})
|
464 |
+
|
465 |
+
conn = get_db_connection()
|
466 |
+
conn.execute('''
|
467 |
+
CREATE TABLE IF NOT EXISTS telegram_analysis (
|
468 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
469 |
+
user_id INTEGER,
|
470 |
+
data TEXT,
|
471 |
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
472 |
+
FOREIGN KEY(user_id) REFERENCES users(id)
|
473 |
+
)
|
474 |
+
''')
|
475 |
+
conn.execute(
|
476 |
+
"INSERT INTO telegram_analysis (user_id, data) VALUES (?, ?)",
|
477 |
+
(current_user.id, json.dumps(results))
|
478 |
+
)
|
479 |
+
conn.commit()
|
480 |
+
|
481 |
+
return jsonify({
|
482 |
+
'status': 'success',
|
483 |
+
'message_count': len(results),
|
484 |
+
})
|
485 |
+
|
486 |
+
except Exception as e:
|
487 |
+
print(f"Error during analysis: {e}")
|
488 |
+
return jsonify({'error': f'Server error: {str(e)}'}), 500
|
489 |
+
finally:
|
490 |
+
conn.close()
|
491 |
+
|
492 |
+
|
493 |
@app.route('/get_chats')
|
494 |
@login_required
|
495 |
def get_chats():
|
496 |
conn = get_db_connection()
|
497 |
try:
|
498 |
chats = conn.execute(
|
499 |
+
"SELECT chat_id, title, created_at FROM chats WHERE user_id = ? ORDER BY created_at DESC",
|
500 |
(current_user.id,)
|
501 |
).fetchall()
|
502 |
return jsonify([dict(chat) for chat in chats])
|
|
|
507 |
@app.route('/start_chat', methods=['POST'])
|
508 |
@login_required
|
509 |
def start_chat():
|
|
|
510 |
try:
|
511 |
chat_id = str(uuid.uuid4())
|
512 |
+
title = f"Чат от {datetime.now().strftime('%d.%m.%Y %H:%M')}"
|
513 |
+
|
514 |
+
conn = get_db_connection()
|
515 |
conn.execute(
|
516 |
+
"INSERT INTO chats (chat_id, user_id, created_at, title) VALUES (?, ?, ?, ?)",
|
517 |
+
(chat_id, current_user.id, datetime.now(), title)
|
518 |
)
|
519 |
conn.commit()
|
520 |
+
|
521 |
+
return jsonify({
|
522 |
+
"success": True,
|
523 |
+
"chat_id": chat_id,
|
524 |
+
"title": title
|
525 |
+
})
|
526 |
except Exception as e:
|
527 |
return jsonify({"error": str(e)}), 500
|
528 |
finally:
|
529 |
conn.close()
|
530 |
|
531 |
|
532 |
+
@app.route('/delete_chat/<chat_id>', methods=['DELETE'])
|
533 |
+
@login_required
|
534 |
+
def delete_chat(chat_id):
|
535 |
+
conn = get_db_connection()
|
536 |
+
try:
|
537 |
+
# Удаляем связанные сообщения
|
538 |
+
conn.execute("DELETE FROM messages WHERE chat_id = ?", (chat_id,))
|
539 |
+
# Удаляем сам чат
|
540 |
+
conn.execute("DELETE FROM chats WHERE chat_id = ? AND user_id = ?", (chat_id, current_user.id))
|
541 |
+
conn.commit()
|
542 |
+
return jsonify({"success": True})
|
543 |
+
except Exception as e:
|
544 |
+
return jsonify({"error": str(e)}), 500
|
545 |
+
finally:
|
546 |
+
conn.close()
|
547 |
+
|
548 |
+
|
549 |
+
@app.route('/get_telegram_analysis')
|
550 |
+
@login_required
|
551 |
+
def get_telegram_analysis():
|
552 |
+
conn = get_db_connection()
|
553 |
+
try:
|
554 |
+
analyses = conn.execute(
|
555 |
+
"SELECT id, data, created_at FROM telegram_analysis WHERE user_id = ?",
|
556 |
+
(current_user.id,)
|
557 |
+
).fetchall()
|
558 |
+
return jsonify([dict(analysis) for analysis in analyses])
|
559 |
+
except Exception as e:
|
560 |
+
return jsonify({"error": str(e)}), 500
|
561 |
+
finally:
|
562 |
+
conn.close()
|
563 |
+
|
564 |
@app.route('/load_chat/<chat_id>')
|
565 |
@login_required
|
566 |
def load_chat(chat_id):
|
|
|
644 |
finally:
|
645 |
conn.close()
|
646 |
|
647 |
+
|
648 |
+
|
649 |
+
|
650 |
if __name__ == "__main__":
|
651 |
+
app.run(debug=True)
|
652 |
+
|
653 |
+
|
instance/chats.db
CHANGED
Binary files a/instance/chats.db and b/instance/chats.db differ
|
|
models.py
CHANGED
@@ -9,6 +9,7 @@ class User(UserMixin, db.Model):
|
|
9 |
username = db.Column(db.String(50), unique=True, nullable=False)
|
10 |
email = db.Column(db.String(100), unique=True, nullable=False)
|
11 |
password_hash = db.Column(db.String(200), nullable=False)
|
|
|
12 |
created_at = db.Column(db.DateTime, default=db.func.current_timestamp())
|
13 |
chats = db.relationship('Chat', backref='user', lazy=True)
|
14 |
reports = db.relationship('AnalysisReport', backref='user', lazy=True)
|
|
|
9 |
username = db.Column(db.String(50), unique=True, nullable=False)
|
10 |
email = db.Column(db.String(100), unique=True, nullable=False)
|
11 |
password_hash = db.Column(db.String(200), nullable=False)
|
12 |
+
is_admin = db.Column(db.Boolean, default=False)
|
13 |
created_at = db.Column(db.DateTime, default=db.func.current_timestamp())
|
14 |
chats = db.relationship('Chat', backref='user', lazy=True)
|
15 |
reports = db.relationship('AnalysisReport', backref='user', lazy=True)
|
requirements.txt
CHANGED
@@ -1,14 +1,16 @@
|
|
1 |
-
flask
|
2 |
-
|
3 |
-
flask-
|
4 |
-
flask-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
|
|
|
|
|
1 |
+
flask==2.3.2
|
2 |
+
werkzeug==2.3.7
|
3 |
+
flask-login==0.6.2
|
4 |
+
flask-sqlalchemy==2.5.1
|
5 |
+
sqlalchemy==1.4.46
|
6 |
+
flask-wtf==1.1.1
|
7 |
+
transformers==4.33.3
|
8 |
+
torch==2.1.0
|
9 |
+
torchaudio==2.1.0
|
10 |
+
pydub==0.25.1
|
11 |
+
librosa==0.10.1
|
12 |
+
numpy==1.24.3
|
13 |
+
gunicorn==21.2.0
|
14 |
+
openai-whisper==20231117
|
15 |
+
python-dotenv==1.0.0
|
16 |
+
email-validator==2.0.0.post2
|