Docfile commited on
Commit
77c5ab3
·
verified ·
1 Parent(s): a8e99a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -61
app.py CHANGED
@@ -1,24 +1,26 @@
1
- from flask import Flask, render_template, request, redirect, url_for, flash
2
  from flask_sqlalchemy import SQLAlchemy
3
- from sqlalchemy import func
4
  from bleach import clean
5
  from bs4 import BeautifulSoup
6
  import os
 
7
  from google import genai
8
  from google.genai import types
9
 
10
- # Clé API Gemini
11
- api_key = "AIzaSyBzv8YdOqVfNlskpAJNvQTPS_AZ-P3t19k"
 
 
12
 
13
- # Configuration de Flask
14
  app = Flask(__name__)
15
- app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get("TOKEN") # Assurez-vous que cette variable est définie
16
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
17
  app.config['SECRET_KEY'] = 'une_cle_secrete_tres_longue' # Clé secrète pour les messages flash
18
 
19
  db = SQLAlchemy(app)
20
 
21
- # --- Modèles ---
22
 
23
  class Matiere(db.Model):
24
  """Modèle représentant une matière."""
@@ -37,7 +39,7 @@ class SousCategorie(db.Model):
37
  nom = db.Column(db.String(64), nullable=False)
38
  matiere_id = db.Column(db.Integer, db.ForeignKey('matiere.id'), nullable=False)
39
  textes = db.relationship('Texte', backref='sous_categorie', lazy='dynamic', cascade="all, delete-orphan")
40
- __table_args__ = (db.UniqueConstraint('nom', 'matiere_id', name='_nom_matiere_uc'),)
41
 
42
  def __repr__(self):
43
  return f"<SousCategorie {self.nom}>"
@@ -53,10 +55,11 @@ class Texte(db.Model):
53
  def __repr__(self):
54
  return f"<Texte {self.titre}>"
55
 
 
56
  # --- Fonctions utilitaires ---
57
 
58
  def sanitize_html(html_content):
59
- """Assainit le contenu HTML."""
60
  allowed_tags = [
61
  'a', 'abbr', 'acronym', 'b', 'blockquote', 'br', 'code', 'div', 'em',
62
  'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p',
@@ -75,14 +78,41 @@ def sanitize_html(html_content):
75
  tag.decompose()
76
  return str(soup)
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  # --- Routes ---
79
 
80
  @app.route('/', methods=['GET', 'POST'])
81
  def gere():
82
  if request.method == 'POST':
 
83
  action = request.form.get('action')
84
 
85
- # Ajouter une matière
86
  if action == 'add_matiere':
87
  nom_matiere = request.form.get('nom_matiere')
88
  if nom_matiere:
@@ -95,7 +125,6 @@ def gere():
95
  db.session.rollback()
96
  flash(f"Erreur lors de l'ajout de la matière : {e}", 'danger')
97
 
98
- # Ajouter une sous-catégorie
99
  elif action == 'add_sous_categorie':
100
  nom_sous_categorie = request.form.get('nom_sous_categorie')
101
  matiere_id = request.form.get('matiere_id')
@@ -108,59 +137,28 @@ def gere():
108
  except Exception as e:
109
  db.session.rollback()
110
  flash(f"Erreur : {e}", 'danger')
111
-
112
- # Ajouter un texte avec génération IA
113
  elif action == 'add_texte':
114
  titre_texte = request.form.get('titre_texte')
 
115
  sous_categorie_id = request.form.get('sous_categorie_id')
116
- youtube_url = request.form.get('youtube_url')
117
- prompt = request.form.get('prompt')
118
- model = request.form.get('model')
119
 
120
- if titre_texte and sous_categorie_id and youtube_url and prompt and model:
 
 
 
 
121
  try:
122
- # Configurer le client Gemini
123
- client = genai.Client(api_key=api_key)
124
-
125
- # Préparer la requête pour l'IA
126
- contents = types.Content(
127
- parts=[
128
- types.Part(text=prompt),
129
- types.Part(file_data=types.FileData(file_uri=youtube_url))
130
- ]
131
- )
132
-
133
- # Générer le contenu avec le modèle sélectionné
134
- response = client.models.generate_content(
135
- model=model,
136
- contents=contents
137
- )
138
-
139
- # Récupérer et assainir le contenu généré
140
- contenu_texte = response.text
141
- contenu_texte_sanitized = sanitize_html(contenu_texte)
142
-
143
- # Ajouter le texte à la base de données
144
- nouveau_texte = Texte(
145
- titre=titre_texte,
146
- contenu=contenu_texte_sanitized,
147
- sous_categorie_id=sous_categorie_id
148
- )
149
- db.session.add(nouvelle_texte)
150
  db.session.commit()
151
  flash(f"Texte '{titre_texte}' ajouté avec succès.", 'success')
152
-
153
  except Exception as e:
154
  db.session.rollback()
155
- flash(f"Erreur lors de la génération ou de l'ajout du texte : {str(e)}", 'danger')
156
- else:
157
- flash("Tous les champs sont requis pour ajouter un texte.", 'warning')
158
 
159
- # Modifier une matière
160
  elif action.startswith('edit_matiere_'):
161
  matiere_id = int(action.split('_')[-1])
162
  matiere = Matiere.query.get_or_404(matiere_id)
163
- matiere.nom = request.form.get(f'edit_nom_matiere_{matiere}')
164
  try:
165
  db.session.commit()
166
  flash(f"Matière '{matiere.nom}' modifiée avec succès.", 'success')
@@ -168,7 +166,6 @@ def gere():
168
  db.session.rollback()
169
  flash(f"Erreur lors de la modification : {e}", 'danger')
170
 
171
- # Modifier une sous-catégorie
172
  elif action.startswith('edit_sous_categorie_'):
173
  sous_categorie_id = int(action.split('_')[-1])
174
  sous_categorie = SousCategorie.query.get_or_404(sous_categorie_id)
@@ -181,7 +178,7 @@ def gere():
181
  db.session.rollback()
182
  flash(f"Erreur : {e}", 'danger')
183
 
184
- # Modifier un texte
185
  elif action.startswith('edit_texte_'):
186
  texte_id = int(action.split('_')[-1])
187
  texte = Texte.query.get_or_404(texte_id)
@@ -190,6 +187,7 @@ def gere():
190
  if contenu:
191
  texte.contenu = sanitize_html(contenu)
192
  texte.sous_categorie_id = request.form.get(f'edit_sous_categorie_id_{texte_id}')
 
193
  try:
194
  db.session.commit()
195
  flash(f"Texte '{texte.titre}' modifié avec succès.", 'success')
@@ -197,7 +195,7 @@ def gere():
197
  db.session.rollback()
198
  flash(f"Erreur : {e}", 'danger')
199
 
200
- # Supprimer une matière
201
  elif action.startswith('delete_matiere_'):
202
  matiere_id = int(action.split('_')[-1])
203
  matiere = Matiere.query.get_or_404(matiere_id)
@@ -209,7 +207,6 @@ def gere():
209
  db.session.rollback()
210
  flash(f"Erreur : {e}", 'danger')
211
 
212
- # Supprimer une sous-catégorie
213
  elif action.startswith('delete_sous_categorie_'):
214
  sous_categorie_id = int(action.split('_')[-1])
215
  sous_categorie = SousCategorie.query.get_or_404(sous_categorie_id)
@@ -218,10 +215,10 @@ def gere():
218
  db.session.commit()
219
  flash(f"Sous-catégorie '{sous_categorie.nom}' supprimée.", 'success')
220
  except Exception as e:
221
- db.session.rollback()
222
- flash(f"Erreur : {e}", 'danger')
 
223
 
224
- # Supprimer un texte
225
  elif action.startswith('delete_texte_'):
226
  texte_id = int(action.split('_')[-1])
227
  texte = Texte.query.get_or_404(texte_id)
@@ -231,17 +228,31 @@ def gere():
231
  flash(f"Texte '{texte.titre}' supprimé avec succès.", 'success')
232
  except Exception as e:
233
  db.session.rollback()
234
- flash(f"Erreur : {e}", 'danger')
235
 
236
  return redirect(url_for('gere'))
237
 
238
- # Récupération des données pour l'affichage
239
  matieres = Matiere.query.order_by(func.lower(Matiere.nom)).all()
240
  sous_categories = SousCategorie.query.order_by(func.lower(SousCategorie.nom)).all()
241
  textes = Texte.query.order_by(Texte.titre).all()
242
  return render_template('gere.html', matieres=matieres, sous_categories=sous_categories, textes=textes)
243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  if __name__ == '__main__':
245
  with app.app_context():
246
  db.create_all() # Crée les tables si elles n'existent pas
247
- app.run(debug=True)
 
1
+ from flask import Flask, render_template, request, redirect, url_for, flash, jsonify
2
  from flask_sqlalchemy import SQLAlchemy
3
+ from sqlalchemy import func # Import func
4
  from bleach import clean
5
  from bs4 import BeautifulSoup
6
  import os
7
+ # Import pour Gemini
8
  from google import genai
9
  from google.genai import types
10
 
11
+ cle = os.environ.get("TOKEN")
12
+ # Clé API Google pour Gemini
13
+ GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "AIzaSyBzv8YdOqVfNlskpAJNvQTPS_AZ-P3t19k")
14
+
15
 
 
16
  app = Flask(__name__)
17
+ app.config['SQLALCHEMY_DATABASE_URI'] = cle
18
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
19
  app.config['SECRET_KEY'] = 'une_cle_secrete_tres_longue' # Clé secrète pour les messages flash
20
 
21
  db = SQLAlchemy(app)
22
 
23
+ # --- Modèles (adaptés de models.py, pour la cohérence) ---
24
 
25
  class Matiere(db.Model):
26
  """Modèle représentant une matière."""
 
39
  nom = db.Column(db.String(64), nullable=False)
40
  matiere_id = db.Column(db.Integer, db.ForeignKey('matiere.id'), nullable=False)
41
  textes = db.relationship('Texte', backref='sous_categorie', lazy='dynamic', cascade="all, delete-orphan")
42
+ __table_args__ = (db.UniqueConstraint('nom', 'matiere_id', name='_nom_matiere_uc'), {})
43
 
44
  def __repr__(self):
45
  return f"<SousCategorie {self.nom}>"
 
55
  def __repr__(self):
56
  return f"<Texte {self.titre}>"
57
 
58
+
59
  # --- Fonctions utilitaires ---
60
 
61
  def sanitize_html(html_content):
62
+ """Assainit le contenu HTML (comme dans ton admin.py)."""
63
  allowed_tags = [
64
  'a', 'abbr', 'acronym', 'b', 'blockquote', 'br', 'code', 'div', 'em',
65
  'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p',
 
78
  tag.decompose()
79
  return str(soup)
80
 
81
+ def generate_content_from_youtube(youtube_url, prompt, model_name):
82
+ """Génère du contenu à partir d'une vidéo YouTube en utilisant l'API Gemini."""
83
+ try:
84
+ # Configuration du client Gemini
85
+ genai.configure(api_key=GEMINI_API_KEY)
86
+ client = genai.Client()
87
+
88
+ # Préparation de la requête
89
+ contents = types.Content(
90
+ parts=[
91
+ types.Part(text=prompt),
92
+ types.Part(
93
+ file_data=types.FileData(file_uri=youtube_url)
94
+ )
95
+ ]
96
+ )
97
+
98
+ # Génération de la réponse
99
+ response = client.models.generate_content(
100
+ model=model_name,
101
+ contents=contents
102
+ )
103
+
104
+ return {"success": True, "text": response.text}
105
+ except Exception as e:
106
+ return {"success": False, "error": str(e)}
107
+
108
  # --- Routes ---
109
 
110
  @app.route('/', methods=['GET', 'POST'])
111
  def gere():
112
  if request.method == 'POST':
113
+ # Traitement des actions (ajout, modification, suppression)
114
  action = request.form.get('action')
115
 
 
116
  if action == 'add_matiere':
117
  nom_matiere = request.form.get('nom_matiere')
118
  if nom_matiere:
 
125
  db.session.rollback()
126
  flash(f"Erreur lors de l'ajout de la matière : {e}", 'danger')
127
 
 
128
  elif action == 'add_sous_categorie':
129
  nom_sous_categorie = request.form.get('nom_sous_categorie')
130
  matiere_id = request.form.get('matiere_id')
 
137
  except Exception as e:
138
  db.session.rollback()
139
  flash(f"Erreur : {e}", 'danger')
 
 
140
  elif action == 'add_texte':
141
  titre_texte = request.form.get('titre_texte')
142
+ contenu_texte = request.form.get('contenu_texte')
143
  sous_categorie_id = request.form.get('sous_categorie_id')
 
 
 
144
 
145
+ if titre_texte and contenu_texte and sous_categorie_id:
146
+ # Assainir le contenu HTML
147
+ contenu_texte_sanitized = sanitize_html(contenu_texte)
148
+ nouveau_texte = Texte(titre=titre_texte, contenu=contenu_texte_sanitized, sous_categorie_id=sous_categorie_id)
149
+ db.session.add(nouveau_texte)
150
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  db.session.commit()
152
  flash(f"Texte '{titre_texte}' ajouté avec succès.", 'success')
 
153
  except Exception as e:
154
  db.session.rollback()
155
+ flash(f"Erreur lors de l'ajout : {e}", 'danger')
156
+
 
157
 
 
158
  elif action.startswith('edit_matiere_'):
159
  matiere_id = int(action.split('_')[-1])
160
  matiere = Matiere.query.get_or_404(matiere_id)
161
+ matiere.nom = request.form.get(f'edit_nom_matiere_{matiere_id}')
162
  try:
163
  db.session.commit()
164
  flash(f"Matière '{matiere.nom}' modifiée avec succès.", 'success')
 
166
  db.session.rollback()
167
  flash(f"Erreur lors de la modification : {e}", 'danger')
168
 
 
169
  elif action.startswith('edit_sous_categorie_'):
170
  sous_categorie_id = int(action.split('_')[-1])
171
  sous_categorie = SousCategorie.query.get_or_404(sous_categorie_id)
 
178
  db.session.rollback()
179
  flash(f"Erreur : {e}", 'danger')
180
 
181
+
182
  elif action.startswith('edit_texte_'):
183
  texte_id = int(action.split('_')[-1])
184
  texte = Texte.query.get_or_404(texte_id)
 
187
  if contenu:
188
  texte.contenu = sanitize_html(contenu)
189
  texte.sous_categorie_id = request.form.get(f'edit_sous_categorie_id_{texte_id}')
190
+
191
  try:
192
  db.session.commit()
193
  flash(f"Texte '{texte.titre}' modifié avec succès.", 'success')
 
195
  db.session.rollback()
196
  flash(f"Erreur : {e}", 'danger')
197
 
198
+
199
  elif action.startswith('delete_matiere_'):
200
  matiere_id = int(action.split('_')[-1])
201
  matiere = Matiere.query.get_or_404(matiere_id)
 
207
  db.session.rollback()
208
  flash(f"Erreur : {e}", 'danger')
209
 
 
210
  elif action.startswith('delete_sous_categorie_'):
211
  sous_categorie_id = int(action.split('_')[-1])
212
  sous_categorie = SousCategorie.query.get_or_404(sous_categorie_id)
 
215
  db.session.commit()
216
  flash(f"Sous-catégorie '{sous_categorie.nom}' supprimée.", 'success')
217
  except Exception as e:
218
+ db.session.rollback()
219
+ flash(f"Erreur : {e}", 'danger')
220
+
221
 
 
222
  elif action.startswith('delete_texte_'):
223
  texte_id = int(action.split('_')[-1])
224
  texte = Texte.query.get_or_404(texte_id)
 
228
  flash(f"Texte '{texte.titre}' supprimé avec succès.", 'success')
229
  except Exception as e:
230
  db.session.rollback()
231
+ flash(f"Erreur : {e}",'danger')
232
 
233
  return redirect(url_for('gere'))
234
 
235
+ # Récupération de toutes les données pour l'affichage
236
  matieres = Matiere.query.order_by(func.lower(Matiere.nom)).all()
237
  sous_categories = SousCategorie.query.order_by(func.lower(SousCategorie.nom)).all()
238
  textes = Texte.query.order_by(Texte.titre).all()
239
  return render_template('gere.html', matieres=matieres, sous_categories=sous_categories, textes=textes)
240
 
241
+ @app.route('/generate-content', methods=['POST'])
242
+ def generate_content():
243
+ """Route API pour générer du contenu avec Gemini."""
244
+ data = request.json
245
+ youtube_url = data.get('youtube_url')
246
+ prompt = data.get('prompt')
247
+ model = data.get('model')
248
+
249
+ if not youtube_url or not prompt or not model:
250
+ return jsonify({'success': False, 'error': 'Paramètres manquants'})
251
+
252
+ result = generate_content_from_youtube(youtube_url, prompt, model)
253
+ return jsonify(result)
254
+
255
  if __name__ == '__main__':
256
  with app.app_context():
257
  db.create_all() # Crée les tables si elles n'existent pas
258
+ app.run(debug=True) # Port différent pour éviter les conflits