Skip to content

Commit e720e74

Browse files
committed
fix 3
1 parent 456613c commit e720e74

3 files changed

Lines changed: 134 additions & 36 deletions

File tree

app/core/simple_config.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ def validate_required_fields(self) -> None:
4545

4646
if missing_fields:
4747
raise ValueError(f"Missing required environment variables: {', '.join(missing_fields)}")
48+
49+
def has_whatsapp_config(self) -> bool:
50+
"""Check if all WhatsApp configuration is available."""
51+
required = [
52+
self.PHONE_NUMBER_ID,
53+
self.ACCESS_TOKEN_LTM,
54+
self.CALLBACK_URL,
55+
self.VERIFY_TOKEN,
56+
self.APP_ID,
57+
self.APP_SECRET,
58+
]
59+
return all(required)
4860

4961

5062
# Try to use pydantic-settings, fall back to simple settings

app/main.py

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,34 +42,59 @@ def create_app() -> FastAPI:
4242
)
4343

4444
# Initialize WhatsApp bot service if available
45+
bot_service = None
4546
if WHATSAPP_AVAILABLE:
4647
try:
4748
from app.services.whatsapp_bot import WhatsAppBotService
4849
bot_service = WhatsAppBotService(app)
49-
print("✅ WhatsApp bot service initialized successfully")
50+
print("✅ WhatsApp bot service created (lazy initialization)")
5051
except Exception as e:
51-
print(f"⚠️ Failed to initialize WhatsApp bot service: {e}")
52+
print(f"⚠️ Failed to create WhatsApp bot service: {e}")
5253
else:
5354
print("⚠️ WhatsApp bot service not available - running in API-only mode")
5455

56+
@app.on_event("startup")
57+
async def startup_event():
58+
"""Initialize services on startup."""
59+
if bot_service:
60+
# Try to initialize WhatsApp in the background
61+
try:
62+
if bot_service.initialize_whatsapp():
63+
print("✅ WhatsApp service initialized on startup")
64+
else:
65+
print("⚠️ WhatsApp service initialization failed")
66+
except Exception as e:
67+
print(f"⚠️ WhatsApp service startup error: {e}")
68+
5569
@app.get("/")
5670
async def health_check():
5771
"""Health check endpoint."""
72+
whatsapp_status = False
73+
if bot_service:
74+
whatsapp_status = bot_service.is_initialized
75+
5876
return {
5977
"status": "healthy",
6078
"message": "Crop Disease Detection Bot is running",
6179
"version": "1.0.0",
62-
"whatsapp_enabled": WHATSAPP_AVAILABLE
80+
"whatsapp_enabled": WHATSAPP_AVAILABLE,
81+
"whatsapp_initialized": whatsapp_status
6382
}
6483

6584
@app.get("/health")
6685
async def detailed_health_check():
6786
"""Detailed health check endpoint."""
6887
components = {
6988
"api": "active",
70-
"whatsapp_bot": "active" if WHATSAPP_AVAILABLE else "disabled",
89+
"whatsapp_bot": "disabled",
7190
}
7291

92+
if WHATSAPP_AVAILABLE:
93+
if bot_service and bot_service.is_initialized:
94+
components["whatsapp_bot"] = "active"
95+
else:
96+
components["whatsapp_bot"] = "available_but_not_initialized"
97+
7398
try:
7499
# Try to check if ML model can be loaded
75100
from app.models.prediction import predict_image
@@ -84,6 +109,23 @@ async def detailed_health_check():
84109
"components": components
85110
}
86111

112+
@app.post("/initialize-whatsapp")
113+
async def initialize_whatsapp_endpoint():
114+
"""Manually initialize WhatsApp service."""
115+
if not WHATSAPP_AVAILABLE:
116+
return {"status": "error", "message": "WhatsApp dependencies not available"}
117+
118+
if not bot_service:
119+
return {"status": "error", "message": "WhatsApp bot service not created"}
120+
121+
try:
122+
if bot_service.initialize_whatsapp():
123+
return {"status": "success", "message": "WhatsApp service initialized"}
124+
else:
125+
return {"status": "error", "message": "WhatsApp initialization failed"}
126+
except Exception as e:
127+
return {"status": "error", "message": f"WhatsApp initialization error: {str(e)}"}
128+
87129
return app
88130

89131

app/services/whatsapp_bot.py

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@
1212
MODEL_AVAILABLE = True
1313
except ImportError:
1414
MODEL_AVAILABLE = False
15+
predict_image = None
1516
print("Warning: ML model not available")
1617

1718
try:
1819
from app.data.disease_info import return_info, cart
1920
DATA_AVAILABLE = True
2021
except ImportError:
2122
DATA_AVAILABLE = False
23+
return_info = None
24+
cart = None
2225
print("Warning: Disease info data not available")
2326

2427

@@ -30,31 +33,56 @@ def __init__(self, app):
3033
self.app = app
3134
self.user_languages: Dict[str, str] = {}
3235
self.translator = Translator()
36+
self.wa = None
37+
self.is_initialized = False
38+
self.settings = get_settings()
3339

34-
# Get settings
35-
settings = get_settings()
40+
# Don't initialize WhatsApp immediately - do it lazily
41+
logging.info("WhatsApp bot service created (lazy initialization)")
42+
43+
def _ensure_whatsapp_initialized(self) -> bool:
44+
"""Ensure WhatsApp client is initialized. Returns True if successful."""
45+
if self.is_initialized and self.wa is not None:
46+
return True
47+
48+
# Check if WhatsApp configuration is complete
49+
if not self.settings.has_whatsapp_config():
50+
logging.warning("WhatsApp configuration incomplete. Service will be disabled.")
51+
return False
3652

3753
try:
3854
self.wa = WhatsApp(
39-
phone_id=settings.PHONE_NUMBER_ID,
40-
token=settings.ACCESS_TOKEN_LTM,
55+
phone_id=self.settings.PHONE_NUMBER_ID,
56+
token=self.settings.ACCESS_TOKEN_LTM,
4157
server=self.app,
42-
callback_url=settings.CALLBACK_URL,
43-
verify_token=settings.VERIFY_TOKEN,
44-
app_id=settings.APP_ID,
45-
app_secret=settings.APP_SECRET,
58+
callback_url=self.settings.CALLBACK_URL,
59+
verify_token=self.settings.VERIFY_TOKEN,
60+
app_id=self.settings.APP_ID,
61+
app_secret=self.settings.APP_SECRET,
4662
)
63+
self._register_handlers()
64+
self.is_initialized = True
4765
logging.info("WhatsApp client initialized successfully.")
66+
return True
4867
except Exception as e:
4968
logging.error(f"Failed to initialize WhatsApp client: {e}")
50-
raise
51-
52-
self._register_handlers()
69+
logging.warning("WhatsApp service will be disabled.")
70+
return False
5371

5472
def _register_handlers(self) -> None:
5573
"""Register message handlers."""
56-
self.wa.on_message(filters.matches("Hello", "Hi", ignore_case=True))(self.handle_menu)
57-
self.wa.on_message(filters.image)(self.handle_analyze)
74+
if self.wa is None:
75+
return
76+
try:
77+
self.wa.on_message(filters.matches("Hello", "Hi", ignore_case=True))(self.handle_menu)
78+
self.wa.on_message(filters.image)(self.handle_analyze)
79+
logging.info("WhatsApp handlers registered successfully.")
80+
except Exception as e:
81+
logging.error(f"Failed to register WhatsApp handlers: {e}")
82+
83+
def initialize_whatsapp(self) -> bool:
84+
"""Public method to initialize WhatsApp service."""
85+
return self._ensure_whatsapp_initialized()
5886

5987
async def translate_text(self, text: str, dest: str) -> str:
6088
"""Translate text to the specified language."""
@@ -93,6 +121,10 @@ async def prompt_language(self, msg: types.Message) -> str:
93121

94122
async def handle_menu(self, _, msg: types.Message) -> None:
95123
"""Handle greeting messages and language selection."""
124+
if not self._ensure_whatsapp_initialized():
125+
logging.error("WhatsApp service not available")
126+
return
127+
96128
language = await self.prompt_language(msg)
97129
self.user_languages[str(msg.from_user)] = language
98130

@@ -104,6 +136,11 @@ async def handle_menu(self, _, msg: types.Message) -> None:
104136
async def handle_analyze(self, _, msg: types.Message) -> None:
105137
"""Handle image analysis requests."""
106138
try:
139+
# Check if ML model is available
140+
if not MODEL_AVAILABLE:
141+
await msg.reply("Sorry, the disease detection service is currently unavailable.")
142+
return
143+
107144
# Get or prompt for user language
108145
if str(msg.from_user) in self.user_languages:
109146
language = self.user_languages[str(msg.from_user)]
@@ -120,27 +157,34 @@ async def handle_analyze(self, _, msg: types.Message) -> None:
120157
await msg.reply(text=process_warn)
121158

122159
# Predict disease
123-
image_disease = predict_image(original_img)
124-
product = cart(image_disease)
125-
126-
# Send response
127-
if product is not None:
128-
translated_info = await self.translate_text(
129-
return_info(image_disease), language
130-
)
131-
translated_product = await self.translate_text(product[0], language)
160+
if MODEL_AVAILABLE and predict_image is not None:
161+
image_disease = predict_image(original_img)
132162

133-
await msg.reply(
134-
text=translated_info,
135-
buttons=types.ButtonUrl(
136-
title=translated_product[:20], url=product[1]
137-
),
138-
)
163+
if DATA_AVAILABLE and cart is not None and return_info is not None:
164+
product = cart(image_disease)
165+
166+
# Send response
167+
if product is not None:
168+
translated_info = await self.translate_text(
169+
return_info(image_disease), language
170+
)
171+
translated_product = await self.translate_text(product[0], language)
172+
173+
await msg.reply(
174+
text=translated_info,
175+
buttons=types.ButtonUrl(
176+
title=translated_product[:20], url=product[1]
177+
),
178+
)
179+
else:
180+
translated_info = await self.translate_text(
181+
return_info(image_disease), language
182+
)
183+
await msg.reply(text=translated_info)
184+
else:
185+
await msg.reply(f"Detected disease: {image_disease}")
139186
else:
140-
translated_info = await self.translate_text(
141-
return_info(image_disease), language
142-
)
143-
await msg.reply(text=translated_info)
187+
await msg.reply("Disease detection service is currently unavailable.")
144188

145189
except Exception as e:
146190
logging.error(f"Error in analyze function: {e}")

0 commit comments

Comments
 (0)