mohamedtsou commited on
Commit
072d28e
·
verified ·
1 Parent(s): 7037995

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -9
app.py CHANGED
@@ -82,6 +82,116 @@ def decode_barcode(image_bytes):
82
  logger.error(f"Decode error: {e}")
83
  return {'success': False, 'error': str(e)}
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  @app.route('/api/scan', methods=['POST', 'GET'])
86
  def scan():
87
  """Endpoint principal - supporte GET pour l'interface web"""
@@ -112,7 +222,6 @@ def scan():
112
  <script>
113
  let currentImage = null;
114
 
115
- // Accéder à la caméra
116
  async function startCamera() {
117
  const video = document.getElementById('preview');
118
  try {
@@ -128,7 +237,6 @@ def scan():
128
  }
129
  }
130
 
131
- // Capturer une image
132
  async function captureImage() {
133
  const video = document.getElementById('preview');
134
  if (!video.srcObject) {
@@ -146,7 +254,6 @@ def scan():
146
  scanBarcode(currentImage);
147
  }
148
 
149
- // Uploader une image
150
  function uploadImage() {
151
  const input = document.getElementById('imageInput');
152
  input.click();
@@ -161,7 +268,6 @@ def scan():
161
  };
162
  }
163
 
164
- // Scanner le code-barres
165
  async function scanBarcode(imageData) {
166
  const resultDiv = document.getElementById('result');
167
  resultDiv.innerHTML = '⌛ Analyse en cours...';
@@ -196,7 +302,6 @@ def scan():
196
  }
197
  }
198
 
199
- // Obtenir les infos produit
200
  async function getProductInfo(barcode) {
201
  const resultDiv = document.getElementById('result');
202
  resultDiv.innerHTML += '<p>🔍 Recherche des infos produit...</p>';
@@ -223,7 +328,6 @@ def scan():
223
  }
224
  }
225
 
226
- // Démarrer la caméra au chargement
227
  window.onload = startCamera;
228
  </script>
229
  </body>
@@ -243,8 +347,8 @@ def scan():
243
  if ',' in image_data:
244
  image_data = image_data.split(',')[1]
245
 
246
- # Limiter la taille pour HF Spaces
247
- if len(image_data) > 3 * 1024 * 1024: # 3MB max
248
  return jsonify({'success': False, 'error': 'Image too large (max 3MB)'}), 400
249
 
250
  image_bytes = base64.b64decode(image_data)
@@ -334,7 +438,14 @@ def health():
334
  'status': 'healthy',
335
  'service': 'Barcode Scanner API',
336
  'version': '2.0',
337
- 'deployed_on': 'Hugging Face Spaces' if HF_SPACE else 'Local'
 
 
 
 
 
 
 
338
  })
339
 
340
  @app.route('/')
@@ -343,6 +454,8 @@ def home():
343
  return jsonify({
344
  'message': 'Barcode Scanner API',
345
  'documentation': {
 
 
346
  'scan': 'POST /api/scan - Scanner un code-barres',
347
  'product': 'GET /api/product/<barcode> - Infos produit',
348
  'health': 'GET /api/health - Health check'
 
82
  logger.error(f"Decode error: {e}")
83
  return {'success': False, 'error': str(e)}
84
 
85
+ # ========== API POUR FLUTTER (Compatibilité) ==========
86
+
87
+ @app.route('/api/decode-barcode', methods=['POST'])
88
+ def decode_barcode_api():
89
+ """Compatibilité avec le code Flutter existant"""
90
+ try:
91
+ if not request.is_json:
92
+ return jsonify({'success': False, 'error': 'Content-Type must be application/json'}), 400
93
+
94
+ data = request.get_json()
95
+ if not data or 'image' not in data:
96
+ return jsonify({'success': False, 'error': 'No image provided'}), 400
97
+
98
+ image_data = data['image']
99
+ if ',' in image_data:
100
+ image_data = image_data.split(',')[1]
101
+
102
+ # Limiter la taille
103
+ if len(image_data) > 3 * 1024 * 1024:
104
+ return jsonify({'success': False, 'error': 'Image too large (max 3MB)'}), 400
105
+
106
+ image_bytes = base64.b64decode(image_data)
107
+ result = decode_barcode(image_bytes)
108
+
109
+ return jsonify(result)
110
+
111
+ except Exception as e:
112
+ logger.error(f"Decode barcode error: {e}")
113
+ return jsonify({'success': False, 'error': str(e)}), 500
114
+
115
+ @app.route('/api/product-info/<barcode>', methods=['GET'])
116
+ def product_info_api(barcode):
117
+ """Compatibilité avec le code Flutter existant"""
118
+ try:
119
+ # Base de données locale
120
+ products = {
121
+ '5901234123457': {
122
+ 'name': 'Lait UHT Demi-écrémé',
123
+ 'brand': 'Candia',
124
+ 'category': 'Alimentation',
125
+ 'price': 1.20,
126
+ 'description': 'Lait stérilisé UHT'
127
+ },
128
+ '9780201379624': {
129
+ 'name': 'Flutter Cookbook',
130
+ 'brand': "O'Reilly",
131
+ 'category': 'Livres',
132
+ 'price': 45.99,
133
+ 'description': 'Guide de développement Flutter'
134
+ },
135
+ '3017620422003': {
136
+ 'name': 'Nutella',
137
+ 'brand': 'Ferrero',
138
+ 'category': 'Alimentation',
139
+ 'price': 4.99,
140
+ 'description': 'Pâte à tartiner aux noisettes'
141
+ },
142
+ '1234567890123': {
143
+ 'name': 'iPhone 13 Pro',
144
+ 'brand': 'Apple',
145
+ 'category': 'Électronique',
146
+ 'price': 1099.99,
147
+ 'description': 'Smartphone Apple avec écran Super Retina XDR'
148
+ }
149
+ }
150
+
151
+ if barcode in products:
152
+ return jsonify({
153
+ 'success': True,
154
+ 'product': products[barcode]
155
+ })
156
+
157
+ # Essayer OpenFoodFacts
158
+ try:
159
+ response = requests.get(
160
+ f'https://world.openfoodfacts.org/api/v0/product/{barcode}.json',
161
+ timeout=3
162
+ )
163
+
164
+ if response.status_code == 200:
165
+ data = response.json()
166
+ if data.get('status') == 1:
167
+ product = data.get('product', {})
168
+ return jsonify({
169
+ 'success': True,
170
+ 'product': {
171
+ 'name': product.get('product_name', 'Produit inconnu'),
172
+ 'brand': product.get('brands', 'Marque inconnue'),
173
+ 'category': product.get('categories', 'Non catégorisé'),
174
+ 'description': product.get('generic_name', ''),
175
+ 'quantity': product.get('quantity', ''),
176
+ 'image_url': product.get('image_url', '')
177
+ },
178
+ 'source': 'openfoodfacts'
179
+ })
180
+ except Exception as e:
181
+ logger.debug(f"OpenFoodFacts error: {e}")
182
+
183
+ return jsonify({
184
+ 'success': False,
185
+ 'error': 'Produit non trouvé',
186
+ 'barcode': barcode
187
+ })
188
+
189
+ except Exception as e:
190
+ logger.error(f"Product info error: {e}")
191
+ return jsonify({'success': False, 'error': str(e)}), 500
192
+
193
+ # ========== API STANDARD ==========
194
+
195
  @app.route('/api/scan', methods=['POST', 'GET'])
196
  def scan():
197
  """Endpoint principal - supporte GET pour l'interface web"""
 
222
  <script>
223
  let currentImage = null;
224
 
 
225
  async function startCamera() {
226
  const video = document.getElementById('preview');
227
  try {
 
237
  }
238
  }
239
 
 
240
  async function captureImage() {
241
  const video = document.getElementById('preview');
242
  if (!video.srcObject) {
 
254
  scanBarcode(currentImage);
255
  }
256
 
 
257
  function uploadImage() {
258
  const input = document.getElementById('imageInput');
259
  input.click();
 
268
  };
269
  }
270
 
 
271
  async function scanBarcode(imageData) {
272
  const resultDiv = document.getElementById('result');
273
  resultDiv.innerHTML = '⌛ Analyse en cours...';
 
302
  }
303
  }
304
 
 
305
  async function getProductInfo(barcode) {
306
  const resultDiv = document.getElementById('result');
307
  resultDiv.innerHTML += '<p>🔍 Recherche des infos produit...</p>';
 
328
  }
329
  }
330
 
 
331
  window.onload = startCamera;
332
  </script>
333
  </body>
 
347
  if ',' in image_data:
348
  image_data = image_data.split(',')[1]
349
 
350
+ # Limiter la taille
351
+ if len(image_data) > 3 * 1024 * 1024:
352
  return jsonify({'success': False, 'error': 'Image too large (max 3MB)'}), 400
353
 
354
  image_bytes = base64.b64decode(image_data)
 
438
  'status': 'healthy',
439
  'service': 'Barcode Scanner API',
440
  'version': '2.0',
441
+ 'deployed_on': 'Hugging Face Spaces' if HF_SPACE else 'Local',
442
+ 'endpoints': {
443
+ '/api/decode-barcode': 'POST - Scanner code-barres (Flutter)',
444
+ '/api/product-info/<barcode>': 'GET - Infos produit (Flutter)',
445
+ '/api/scan': 'POST/GET - Scanner code-barres',
446
+ '/api/product/<barcode>': 'GET - Infos produit',
447
+ '/api/health': 'GET - Health check'
448
+ }
449
  })
450
 
451
  @app.route('/')
 
454
  return jsonify({
455
  'message': 'Barcode Scanner API',
456
  'documentation': {
457
+ 'decode-barcode': 'POST /api/decode-barcode - Scanner un code-barres (Flutter)',
458
+ 'product-info': 'GET /api/product-info/<barcode> - Infos produit (Flutter)',
459
  'scan': 'POST /api/scan - Scanner un code-barres',
460
  'product': 'GET /api/product/<barcode> - Infos produit',
461
  'health': 'GET /api/health - Health check'