beeproject / app.py
abidjoyia's picture
Upload 6 files
3cd2ab5 verified
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
@app.route('/forgot_password', methods=['POST'])
def forgot_password_endpoint():
return forgot_password(request)
# Verify reset code endpoint
@app.route('/verify_reset_code', methods=['POST'])
def verify_reset_code_route():
return verify_reset_code_endpoint(request)
# Reset password endpoint
@app.route('/reset_password', methods=['POST'])
def reset_password_endpoint():
return reset_password(request)
@app.route('/change_password', methods=['POST'])
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)
@app.route('/predict', methods=['POST'])
def predict():
return handle_predict(request, save_prediction)
@app.route('/signup', methods=['POST'])
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
@app.route('/login', methods=['POST'])
def login():
data = request.json
result = authenticate_user(data['email'], data['password'])
if "error" in result:
return jsonify(result), 415
return jsonify(result), 200
@app.route('/profile', methods=['GET'])
def profile():
user_id = request.args.get('user_id')
return jsonify(get_user_profile(user_id))
@app.route('/profile/update', methods=['POST'])
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']
))
@app.route('/history', methods=['GET'])
def history():
user_id = request.args.get('user_id')
return jsonify({"history": get_history(user_id)})
@app.route('/farm', methods=['GET'])
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
@app.route('/farm/update', methods=['POST'])
def update_farm():
data = request.json
return jsonify(update_farm_details_in_db(
data['user_id'], data['fullname'], data['country'], data['city'], data['zip']
))
@app.route('/farms', methods=['GET'])
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
@app.route('/hives', methods=['GET'])
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)
@app.route('/hives', methods=['POST'])
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
@app.route('/hives', methods=['DELETE'])
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
@app.route('/hive_detail', methods=['GET'])
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)
@app.route('/manual_health_update', methods=['POST'])
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
@app.route('/edit_hive', methods=['POST'])
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
@app.route('/report', methods=['GET'])
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
@app.route('/addtask', methods=['POST'])
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
@app.route('/showtasks', methods=['GET'])
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
@app.route('/task_detail', methods=['GET'])
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
@app.route('/task_complete', methods=['POST'])
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
@app.route('/delete_task', methods=['DELETE'])
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
@app.route('/notifications', methods=['GET'])
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
@app.route('/notifications/mark_read', methods=['POST'])
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
@app.route('/add_notifications', methods=['POST'])
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
@app.route('/check_weather', methods=['POST'])
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)