Spaces:
Running
Running
| import os | |
| os.environ["NUMBA_CACHE_DIR"] = "/tmp/numba_cache" | |
| os.environ["NUMBA_DISABLE_JIT"] = "1" | |
| from apscheduler.schedulers.background import BackgroundScheduler | |
| import requests | |
| import time | |
| import logging | |
| from flask import Flask, request, jsonify, send_file | |
| from flask_cors import CORS | |
| from predict import handle_predict | |
| from database import ( | |
| init_db, save_prediction, get_history, register_user, authenticate_user, | |
| get_user_profile, update_user_profile, get_farm_details_from_db, | |
| update_farm_details_in_db, get_farm_detailss_from_db, get_hives_from_db, | |
| get_hive_detail_from_db, add_hive_to_db, delete_hive_from_db, update_hive_health_in_db, | |
| add_task_to_db, get_user_tasks_from_db, get_task_detail_from_db, | |
| delete_task_from_db, update_task_status_to_completed, update_hive_in_db, | |
| generate_reset_code, verify_reset_code, update_user_password, change_user_password, get_all_notifications, add_notification, | |
| mark_notification_as_read, get_user_cities | |
| ) | |
| from forget import forgot_password, verify_reset_code_endpoint, reset_password | |
| from report import generate_report | |
| from datetime import datetime | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
| logger = logging.getLogger(__name__) | |
| app = Flask(__name__) | |
| app.secret_key = os.urandom(24) | |
| CORS(app) | |
| # Forgot password endpoint | |
| def forgot_password_endpoint(): | |
| return forgot_password(request) | |
| # Verify reset code endpoint | |
| def verify_reset_code_route(): | |
| return verify_reset_code_endpoint(request) | |
| # Reset password endpoint | |
| def reset_password_endpoint(): | |
| return reset_password(request) | |
| def change_password(): | |
| data = request.json | |
| user_id = data.get('user_id') | |
| current_password = data.get('password') | |
| new_password = data.get('new_password') | |
| if not all([user_id, current_password, new_password]): | |
| return jsonify({"error": "Missing required fields"}), 400 | |
| result = change_user_password(user_id, current_password, new_password) | |
| if result: | |
| return jsonify({"message": "Password changed successfully"}), 200 | |
| return jsonify({"error": "Current password incorrect"}), 401 | |
| # Existing endpoints (unchanged) | |
| def predict(): | |
| return handle_predict(request, save_prediction) | |
| def signup(): | |
| data = request.json | |
| result = register_user(data['fullName'], data['email'], data['password']) | |
| if result == "email already exist": | |
| return jsonify({"message": result}), 215 | |
| return jsonify({"message": result}), 200 | |
| def login(): | |
| data = request.json | |
| result = authenticate_user(data['email'], data['password']) | |
| if "error" in result: | |
| return jsonify(result), 415 | |
| return jsonify(result), 200 | |
| def profile(): | |
| user_id = request.args.get('user_id') | |
| return jsonify(get_user_profile(user_id)) | |
| def update_profile(): | |
| data = request.json | |
| return jsonify(update_user_profile( | |
| data['user_id'], data['fullname'], data['country'], data['city'], | |
| data['gender'], data['phone_number'] | |
| )) | |
| def history(): | |
| user_id = request.args.get('user_id') | |
| return jsonify({"history": get_history(user_id)}) | |
| def get_farm_details(): | |
| user_id = request.args.get('user_id') | |
| if not user_id: | |
| return jsonify({"error": "User ID is required"}), 400 | |
| farm = get_farm_details_from_db(user_id) | |
| return jsonify(farm) if farm else jsonify({"error": "Farm details not found"}), 404 | |
| def update_farm(): | |
| data = request.json | |
| return jsonify(update_farm_details_in_db( | |
| data['user_id'], data['fullname'], data['country'], data['city'], data['zip'] | |
| )) | |
| def get_farm(): | |
| user_id = request.args.get('user_id') | |
| if not user_id: | |
| return jsonify({"error": "User ID is required"}), 400 | |
| farm = get_farm_details_from_db(user_id) | |
| return jsonify(farm) if farm else jsonify({"error": "No farm registered"}), 404 | |
| def get_hives(): | |
| farm_id = request.args.get('farm_id') | |
| if not farm_id: | |
| return jsonify({"error": "Farm ID is required"}), 400 | |
| hives = get_hives_from_db(farm_id) | |
| return jsonify(hives) | |
| def add_hive(): | |
| data = request.json | |
| if not all(key in data for key in ['farm_id', 'hive_number', 'bee_type', 'number_of_frames', 'health_status']): | |
| return jsonify({"error": "Missing required fields"}), 400 | |
| try: | |
| hive_id = add_hive_to_db( | |
| data['farm_id'], | |
| data['hive_number'], | |
| data['bee_type'], | |
| data['number_of_frames'], | |
| data['health_status'], | |
| data.get('notes', '') | |
| ) | |
| return jsonify({"success": True, "hive_id": hive_id}), 201 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def delete_hive(): | |
| hive_id = request.args.get('hive_id') | |
| if not hive_id: | |
| return jsonify({"error": "Hive ID is required"}), 400 | |
| try: | |
| deleted = delete_hive_from_db(hive_id) | |
| if deleted: | |
| return jsonify({"success": True}), 200 | |
| else: | |
| return jsonify({"error": "Hive not found"}), 404 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def get_hives_detail(): | |
| hive_id = request.args.get('hive_id') | |
| if not hive_id: | |
| return jsonify({"error": "Hive Id is required"}), 400 | |
| hivess = get_hive_detail_from_db(hive_id) | |
| return jsonify(hivess) | |
| def update_hive_health(): | |
| data = request.json | |
| if not all(key in data for key in ['hive_id', 'health_status']): | |
| return jsonify({"error": "Missing required fields"}), 400 | |
| try: | |
| update_hive_health_in_db(data['hive_id'], data['health_status']) | |
| return jsonify({"success": True, "message": "Health status updated"}), 200 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def update_hive(): | |
| data = request.json | |
| if 'hive_id' not in data: | |
| return jsonify({"error": "hive_id is required"}), 400 | |
| update_data = {k: v for k, v in data.items() if k in {'hive_id', 'number_of_frames', 'bee_type', 'notes'}} | |
| if len(update_data) <= 1: | |
| return jsonify({"error": "No valid fields provided"}), 400 | |
| try: | |
| result = update_hive_in_db( | |
| update_data['hive_id'], | |
| update_data.get('number_of_frames'), | |
| update_data.get('bee_type'), | |
| update_data.get('notes') | |
| ) | |
| if not result: | |
| return jsonify({"error": "Hive not found"}), 404 | |
| return jsonify({"success": True, "hive_id": update_data['hive_id']}), 200 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def get_report(): | |
| user_id = request.args.get('user_id') | |
| if not user_id: | |
| return jsonify({"error": "User ID is required"}), 400 | |
| try: | |
| buffer = generate_report(user_id) | |
| buffer.seek(0) | |
| return send_file( | |
| buffer, | |
| as_attachment=True, | |
| download_name=f"bee_hive_report_{user_id}_{datetime.now().strftime('%Y%m%d')}.pdf", | |
| mimetype='application/pdf' | |
| ) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def add_task(): | |
| data = request.json | |
| required_fields = ['user_id', 'task_name', 'description', 'deadline_date', 'status'] | |
| if not all(key in data for key in required_fields): | |
| return jsonify({"error": "Missing required fields"}), 400 | |
| try: | |
| task_id = add_task_to_db( | |
| data['user_id'], | |
| data['task_name'], | |
| data.get('hive_id'), | |
| data['description'], | |
| data['deadline_date'], | |
| data['status'] | |
| ) | |
| return jsonify({"success": True, "task_id": task_id}), 201 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def get_user_tasks(): | |
| user_id = request.args.get('user_id') | |
| if not user_id: | |
| return jsonify({"error": "User ID is required"}), 400 | |
| try: | |
| tasks = get_user_tasks_from_db(user_id) | |
| return jsonify({"tasks": tasks}), 200 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def get_task_detail(): | |
| task_id = request.args.get('task_id') | |
| if not task_id: | |
| return jsonify({"error": "Task ID is required"}), 400 | |
| try: | |
| task = get_task_detail_from_db(task_id) | |
| if task: | |
| return jsonify(task), 200 | |
| return jsonify({"error": "Task not found"}), 404 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def mark_task_complete(): | |
| data = request.json | |
| task_id = data.get('task_id') | |
| if not task_id: | |
| return jsonify({"error": "Task ID is required"}), 400 | |
| try: | |
| updated = update_task_status_to_completed(task_id) | |
| if updated: | |
| return jsonify({"success": True, "message": "Task marked as completed"}), 200 | |
| return jsonify({"error": "Task not found"}), 404 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def delete_task(): | |
| data = request.get_json() | |
| task_id = data.get("task_id") if data else None | |
| if not task_id: | |
| return jsonify({"error": "Task ID is required"}), 400 | |
| try: | |
| deleted = delete_task_from_db(task_id) | |
| if deleted: | |
| return jsonify({"success": True}), 200 | |
| else: | |
| return jsonify({"error": "Task not found"}), 404 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def get_notifications(): | |
| user_id = request.args.get('user_id') | |
| if not user_id: | |
| return jsonify({"error": "User ID is required"}), 400 | |
| try: | |
| notifications = get_all_notifications(user_id) | |
| return jsonify({"notifications": notifications}), 200 | |
| except TypeError as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def mark_notifications_read(): | |
| data = request.json | |
| notification_id = data.get('notification_id') | |
| if not notification_id: | |
| return jsonify({"error": "Notification ID is required"}), 400 | |
| try: | |
| mark_notification_as_read(notification_id) | |
| return jsonify({"message": "Notification marked as read"}), 200 | |
| except Exception as e: | |
| return jsonify({"error)": str(e)}), 500 | |
| def create_notification(): | |
| data = request.json | |
| required_fields = ['user_id', 'textt'] | |
| if not all(key in data for key in required_fields): | |
| return jsonify({"error": "Missing required fields"}), 400 | |
| try: | |
| notification_id = add_notification( | |
| data['user_id'], | |
| data['textt'] | |
| ) | |
| return jsonify({"success": True, "notification_id": notification_id}), 201 | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def trigger_weather_check(): | |
| try: | |
| check_weather_conditions() | |
| return jsonify({"message": "Weather check triggered successfully"}), 200 | |
| except Exception as e: | |
| logger.error(f"Error triggering weather check: {str(e)}") | |
| return jsonify({"error": str(e)}), 500 | |
| def check_weather_conditions(): | |
| logger.info("Checking weather conditions for users") | |
| # Wake up the database | |
| try: | |
| response = requests.get("https://bilalhasanniazi-bee-notbee.hf.space/profile?user_id=0") | |
| if response.status_code == 200: | |
| logger.info("Database wake-up API called successfully") | |
| else: | |
| logger.warning(f"Database wake-up API failed with status {response.status_code}") | |
| except Exception as e: | |
| logger.error(f"Error calling database wake-up API: {str(e)}") | |
| # Wait for 10 seconds | |
| time.sleep(10) | |
| user_cities = get_user_cities() | |
| weather_api_key = "9fb23a5a66764b61a43163911251605" | |
| base_url = "http://api.weatherapi.com/v1/forecast.json" | |
| for user_id, city in user_cities.items(): | |
| try: | |
| # Fetch weather data | |
| response = requests.get(f"{base_url}?key={weather_api_key}&q={city}") | |
| if response.status_code != 200: | |
| logger.warning(f"Failed to fetch weather for city {city}: {response.status_code}") | |
| continue | |
| data = response.json() | |
| if "error" in data: | |
| logger.warning(f"Invalid city {city} for user {user_id}: {data['error']['message']}") | |
| continue | |
| temp_c = data["current"]["temp_c"] | |
| if temp_c > 45: | |
| notification_text = "Temperature is too hot, take safety precautions to protect bees" | |
| add_notification(user_id, notification_text) | |
| logger.info(f"Notification added for user {user_id} in {city}: {notification_text}") | |
| except Exception as e: | |
| logger.error(f"Error processing weather for user {user_id}, city {city}: {str(e)}") | |
| # Initialize scheduler | |
| scheduler = BackgroundScheduler() | |
| scheduler.add_job(check_weather_conditions, 'interval', hours=24) | |
| scheduler.start() | |
| if __name__ == '__main__': | |
| logger.info("Starting Flask application") | |
| app.run(debug=False, host='0.0.0.0', port=7860) |