sksameermujahid commited on
Commit
4baa8cd
·
verified ·
1 Parent(s): 4eae7e6

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +177 -39
  2. templates/index.html +54 -4
app.py CHANGED
@@ -1103,6 +1103,90 @@ TWILIO_WHATSAPP_NUMBER = "whatsapp:+14155238886"
1103
  WHATSAPP_CHAR_LIMIT = 1600
1104
  PROPERTY_BASE_URL = "https://hiveprop.com/property/image-slider?id="
1105
  MAX_PROPERTIES_TO_SEND = 5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1106
 
1107
  @app.route('/create_account_and_send_whatsapp', methods=['POST'])
1108
  def create_account_and_send_whatsapp():
@@ -1113,7 +1197,16 @@ def create_account_and_send_whatsapp():
1113
  first_name = data.get('firstName')
1114
  last_name = data.get('lastName')
1115
  phone = data.get('phone')
 
1116
  recommendations = data.get('recommendations', [])
 
 
 
 
 
 
 
 
1117
 
1118
  # Clean and format phone number in E.164
1119
  # Remove all spaces, dashes, and parentheses
@@ -1128,56 +1221,101 @@ def create_account_and_send_whatsapp():
1128
  logger.error(f"Invalid phone number format: {phone}")
1129
  return jsonify({"success": False, "error": "Invalid phone number format. Please provide a valid 10-digit Indian mobile number."}), 400
1130
 
1131
- # Take only the top 10 properties
1132
- top_recommendations = recommendations[:MAX_PROPERTIES_TO_SEND]
 
 
1133
 
1134
- # Prepare the WhatsApp message with improved design
1135
- message_header = f"🏡 *Hello {first_name} {last_name}!*\n\nHere are your *top {MAX_PROPERTIES_TO_SEND} recommended properties* in Hyderabad:\n"
 
 
 
 
 
1136
 
1137
- message_body = ""
1138
- for idx, prop in enumerate(top_recommendations, 1):
1139
- property_name = prop.get('propertyName', 'Unnamed Property')
1140
- property_id = prop.get('id', '')
1141
- property_link = f"{PROPERTY_BASE_URL}{property_id}"
1142
 
1143
- # Extract location from address or description
1144
- address = prop.get('address', '')
1145
- location = address.split(',')[-2].strip() if ',' in address else address
 
 
 
 
 
1146
 
1147
- message_body += f"{idx}️⃣ *{property_name}*\n"
1148
- message_body += f"📍 *{location}*\n"
1149
- message_body += f"🔗{property_link}\n"
1150
 
1151
- # Add a call-to-action
1152
- message_footer = "---\n🔎 *Looking for more options?* Explore all listings at https://hiveprop.com."
 
1153
 
1154
- full_message = message_header + message_body + message_footer
 
1155
 
1156
- # Encode credentials for Basic Auth
1157
- credentials = f"{TWILIO_ACCOUNT_SID}:{TWILIO_AUTH_TOKEN}"
1158
- encoded_credentials = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')
1159
 
1160
- # Send the message
1161
- payload = {
1162
- "To": f"whatsapp:{phone}",
1163
- "From": TWILIO_WHATSAPP_NUMBER,
1164
- "Body": full_message
1165
- }
1166
 
1167
- headers = {
1168
- "Authorization": f"Basic {encoded_credentials}",
1169
- "Content-Type": "application/x-www-form-urlencoded"
1170
- }
 
 
1171
 
1172
- response = requests.post(
1173
- f"https://api.twilio.com/2010-04-01/Accounts/{TWILIO_ACCOUNT_SID}/Messages.json",
1174
- data=payload,
1175
- headers=headers
1176
- )
1177
- response.raise_for_status()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1178
 
1179
- logger.info("WhatsApp message sent successfully")
1180
- return jsonify({"success": True, "message": "Account created and WhatsApp message sent!"})
 
 
 
1181
 
1182
  except requests.exceptions.HTTPError as e:
1183
  logger.error(f"Twilio API error: {e.response.text}")
 
1103
  WHATSAPP_CHAR_LIMIT = 1600
1104
  PROPERTY_BASE_URL = "https://hiveprop.com/property/image-slider?id="
1105
  MAX_PROPERTIES_TO_SEND = 5
1106
+ HIVEPROP_EMAIL_API_URL = "https://hivepropapi.azurewebsites.net/api/Email/sendPlainText"
1107
+
1108
+ def send_email_recommendations(email, first_name, last_name, recommendations):
1109
+ """Send property recommendations via email using HiveProp API"""
1110
+ try:
1111
+ # Take only the top properties
1112
+ top_recommendations = recommendations[:MAX_PROPERTIES_TO_SEND]
1113
+
1114
+ # Prepare email content
1115
+ subject = f"Your Top {MAX_PROPERTIES_TO_SEND} Property Recommendations - HiveProp"
1116
+
1117
+ # Create plain text email body (simpler format for testing)
1118
+ email_body = f"🏡 Hello {first_name} {last_name}!\n\n"
1119
+ email_body += f"Here are your top {MAX_PROPERTIES_TO_SEND} recommended properties in Hyderabad:\n\n"
1120
+
1121
+ if not top_recommendations:
1122
+ email_body += "⚠️ No specific properties found, but you can explore all available properties at https://hiveprop.com\n\n"
1123
+ else:
1124
+ for idx, prop in enumerate(top_recommendations, 1):
1125
+ property_name = prop.get('propertyName', 'Unnamed Property')
1126
+ property_id = prop.get('id', '')
1127
+ property_link = f"{PROPERTY_BASE_URL}{property_id}"
1128
+
1129
+ # Extract location from address or description
1130
+ address = prop.get('address', '')
1131
+ location = address.split(',')[-2].strip() if ',' in address else address
1132
+
1133
+ email_body += f"{idx}. {property_name}\n"
1134
+ email_body += f" 📍 Location: {location}\n"
1135
+ email_body += f" 🔗 {property_link}\n\n"
1136
+
1137
+ email_body += "---\n"
1138
+ email_body += "🔎 Looking for more options? Explore all listings at https://hiveprop.com\n\n"
1139
+ email_body += "Thank you for using HiveProp!\n"
1140
+ email_body += "Best regards,\n"
1141
+ email_body += "The HiveProp Team"
1142
+
1143
+ # Send email via HiveProp API using query parameters
1144
+ params = {
1145
+ 'toEmail': email,
1146
+ 'subject': subject,
1147
+ 'body': email_body
1148
+ }
1149
+
1150
+ logger.info(f"Sending email to {email} via HiveProp API")
1151
+ logger.info(f"API URL: {HIVEPROP_EMAIL_API_URL}")
1152
+ logger.info(f"Subject: {subject}")
1153
+ logger.info(f"Request params: {params}")
1154
+
1155
+ # Send POST request with query parameters
1156
+ response = requests.post(HIVEPROP_EMAIL_API_URL, params=params, timeout=30)
1157
+ logger.info(f"Email API response status: {response.status_code}")
1158
+ logger.info(f"Email API response text: {response.text}")
1159
+
1160
+ # Check for 404 or other errors before raising
1161
+ if response.status_code == 404:
1162
+ logger.error(f"Email API endpoint not found (404): {HIVEPROP_EMAIL_API_URL}")
1163
+ return False, f"Email API endpoint not found. Please check the API URL."
1164
+ elif response.status_code != 200:
1165
+ logger.error(f"Email API returned status {response.status_code}: {response.text}")
1166
+ return False, f"Email API error: Status {response.status_code} - {response.text}"
1167
+
1168
+ response.raise_for_status()
1169
+
1170
+ logger.info(f"Email sent successfully to {email}")
1171
+ return True, "Email sent successfully"
1172
+
1173
+ except requests.exceptions.Timeout:
1174
+ logger.error("HiveProp Email API request timed out")
1175
+ return False, "Email API timeout - service may be slow or unavailable"
1176
+ except requests.exceptions.ConnectionError as e:
1177
+ logger.error(f"HiveProp Email API connection error: {str(e)}")
1178
+ return False, "Email API connection failed - service may be down"
1179
+ except requests.exceptions.HTTPError as e:
1180
+ error_text = e.response.text if e.response else "No response text"
1181
+ status_code = e.response.status_code if e.response else "Unknown"
1182
+ logger.error(f"HiveProp Email API error: Status {status_code}, Response: {error_text}")
1183
+ return False, f"Email API error: Status {status_code} - {error_text}"
1184
+ except requests.exceptions.RequestException as e:
1185
+ logger.error(f"Request error sending email: {str(e)}")
1186
+ return False, f"Email request failed: {str(e)}"
1187
+ except Exception as e:
1188
+ logger.error(f"Unexpected error sending email: {str(e)}")
1189
+ return False, f"Failed to send email: {str(e)}"
1190
 
1191
  @app.route('/create_account_and_send_whatsapp', methods=['POST'])
1192
  def create_account_and_send_whatsapp():
 
1197
  first_name = data.get('firstName')
1198
  last_name = data.get('lastName')
1199
  phone = data.get('phone')
1200
+ email = data.get('email')
1201
  recommendations = data.get('recommendations', [])
1202
+
1203
+ logger.info(f"Received data: firstName={first_name}, lastName={last_name}, email={email}, phone={phone}")
1204
+ logger.info(f"Recommendations count: {len(recommendations)}")
1205
+
1206
+ # Validate email format
1207
+ if not email or '@' not in email:
1208
+ logger.error(f"Invalid email format: {email}")
1209
+ return jsonify({"success": False, "error": "Invalid email format. Please provide a valid email address."}), 400
1210
 
1211
  # Clean and format phone number in E.164
1212
  # Remove all spaces, dashes, and parentheses
 
1221
  logger.error(f"Invalid phone number format: {phone}")
1222
  return jsonify({"success": False, "error": "Invalid phone number format. Please provide a valid 10-digit Indian mobile number."}), 400
1223
 
1224
+ # Track success status for both email and WhatsApp
1225
+ whatsapp_success = False
1226
+ email_success = False
1227
+ messages = []
1228
 
1229
+ # Send via WhatsApp
1230
+ try:
1231
+ # Take only the top properties
1232
+ top_recommendations = recommendations[:MAX_PROPERTIES_TO_SEND]
1233
+
1234
+ logger.info(f"Total recommendations received: {len(recommendations)}")
1235
+ logger.info(f"Top recommendations to send: {len(top_recommendations)}")
1236
 
1237
+ # Prepare the WhatsApp message with improved design
1238
+ message_header = f"🏡 *Hello {first_name} {last_name}!*\n\nHere are your *top {MAX_PROPERTIES_TO_SEND} recommended properties* in Hyderabad:\n"
 
 
 
1239
 
1240
+ message_body = ""
1241
+ if not top_recommendations:
1242
+ message_body = "⚠️ No specific properties found, but you can explore all available properties at https://hiveprop.com\n\n"
1243
+ else:
1244
+ for idx, prop in enumerate(top_recommendations, 1):
1245
+ property_name = prop.get('propertyName', 'Unnamed Property')
1246
+ property_id = prop.get('id', '')
1247
+ property_link = f"{PROPERTY_BASE_URL}{property_id}"
1248
 
1249
+ # Extract location from address or description
1250
+ address = prop.get('address', '')
1251
+ location = address.split(',')[-2].strip() if ',' in address else address
1252
 
1253
+ message_body += f"{idx}️⃣ *{property_name}*\n"
1254
+ message_body += f"📍 *{location}*\n"
1255
+ message_body += f"🔗{property_link}\n\n"
1256
 
1257
+ # Add a call-to-action
1258
+ message_footer = "---\n🔎 *Looking for more options?* Explore all listings at https://hiveprop.com."
1259
 
1260
+ full_message = message_header + message_body + message_footer
1261
+
1262
+ logger.info(f"WhatsApp message length: {len(full_message)}")
1263
 
1264
+ # Encode credentials for Basic Auth
1265
+ credentials = f"{TWILIO_ACCOUNT_SID}:{TWILIO_AUTH_TOKEN}"
1266
+ encoded_credentials = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')
 
 
 
1267
 
1268
+ # Send the message
1269
+ payload = {
1270
+ "To": f"whatsapp:{phone}",
1271
+ "From": TWILIO_WHATSAPP_NUMBER,
1272
+ "Body": full_message
1273
+ }
1274
 
1275
+ headers = {
1276
+ "Authorization": f"Basic {encoded_credentials}",
1277
+ "Content-Type": "application/x-www-form-urlencoded"
1278
+ }
1279
+
1280
+ response = requests.post(
1281
+ f"https://api.twilio.com/2010-04-01/Accounts/{TWILIO_ACCOUNT_SID}/Messages.json",
1282
+ data=payload,
1283
+ headers=headers
1284
+ )
1285
+ response.raise_for_status()
1286
+
1287
+ logger.info("WhatsApp message sent successfully")
1288
+ whatsapp_success = True
1289
+ messages.append("WhatsApp message sent successfully!")
1290
+
1291
+ except requests.exceptions.HTTPError as e:
1292
+ logger.error(f"Twilio API error: {e.response.text}")
1293
+ messages.append(f"WhatsApp error: {e.response.text}")
1294
+ except Exception as e:
1295
+ logger.error(f"Unexpected WhatsApp error: {str(e)}")
1296
+ messages.append(f"WhatsApp error: {str(e)}")
1297
+
1298
+ # Send via Email
1299
+ logger.info(f"Sending email to {email} with {len(recommendations)} recommendations")
1300
+ email_success, email_message = send_email_recommendations(email, first_name, last_name, recommendations)
1301
+ messages.append(email_message)
1302
+
1303
+ # Determine overall success and response message
1304
+ success = whatsapp_success or email_success
1305
+ if whatsapp_success and email_success:
1306
+ overall_message = "Account created! Messages sent via WhatsApp and email!"
1307
+ elif whatsapp_success:
1308
+ overall_message = "Account created! WhatsApp message sent (email failed)"
1309
+ elif email_success:
1310
+ overall_message = "Account created! Email sent (WhatsApp failed)"
1311
+ else:
1312
+ overall_message = "Account created but failed to send messages"
1313
 
1314
+ return jsonify({
1315
+ "success": success,
1316
+ "message": overall_message,
1317
+ "details": messages
1318
+ })
1319
 
1320
  except requests.exceptions.HTTPError as e:
1321
  logger.error(f"Twilio API error: {e.response.text}")
templates/index.html CHANGED
@@ -436,6 +436,11 @@
436
  <div class="form-step" id="step4">
437
  <h4 class="mb-3">Create Your Account</h4>
438
  <p class="mb-4">Join us to get personalized property recommendations</p>
 
 
 
 
 
439
 
440
  <form id="accountForm">
441
  <div class="mb-3">
@@ -456,7 +461,9 @@
456
 
457
  <div class="mb-3">
458
  <label for="phone" class="form-label">Phone Number *</label>
459
- <input type="tel" class="form-control" id="phone" placeholder="e.g., 9876543210" required>
 
 
460
  </div>
461
 
462
  <div class="mb-3">
@@ -812,6 +819,17 @@
812
  document.getElementById('prefBudget').textContent = formData.price_range ? formData.price_range.map(range => `₹${range[0]} - ${range[1] ? `₹${range[1]}` : 'Above'}`).join(', ') : 'Any';
813
  document.getElementById('prefFeatures').textContent = formData.features ? formData.features.join(', ') : 'None';
814
 
 
 
 
 
 
 
 
 
 
 
 
815
  // Handle account form submission
816
  document.getElementById('accountForm').addEventListener('submit', async (e) => {
817
  e.preventDefault();
@@ -819,9 +837,18 @@
819
  const firstName = document.getElementById('firstName').value;
820
  const lastName = document.getElementById('lastName').value;
821
  const email = document.getElementById('email').value;
822
- const phone = document.getElementById('phone').value;
823
  const password = document.getElementById('password').value;
824
 
 
 
 
 
 
 
 
 
 
825
  // Send account details and recommendations to the backend
826
  const accountResponse = await fetch('/create_account_and_send_whatsapp', {
827
  method: 'POST',
@@ -841,10 +868,33 @@
841
  const result = await accountResponse.json();
842
 
843
  if (result.success) {
844
- alert('Account created successfully! Recommendations sent to your WhatsApp.');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
845
  displayRecommendations(recommendations);
846
  } else {
847
- alert('Failed to create account: ' + result.error);
 
 
 
 
 
848
  }
849
  });
850
 
 
436
  <div class="form-step" id="step4">
437
  <h4 class="mb-3">Create Your Account</h4>
438
  <p class="mb-4">Join us to get personalized property recommendations</p>
439
+
440
+ <div class="alert alert-info mb-4" role="alert">
441
+ <h6 class="alert-heading">📱📧 Recommendations Delivery</h6>
442
+ <p class="mb-0">Your property recommendations will be sent to both your WhatsApp and email address automatically!</p>
443
+ </div>
444
 
445
  <form id="accountForm">
446
  <div class="mb-3">
 
461
 
462
  <div class="mb-3">
463
  <label for="phone" class="form-label">Phone Number *</label>
464
+ <input type="tel" class="form-control" id="phone" placeholder="e.g., 9876543210" pattern="[0-9]{10}" maxlength="10" required>
465
+ <div class="form-text">Enter 10-digit mobile number without spaces or special characters</div>
466
+ <div class="invalid-feedback">Please enter a valid 10-digit mobile number.</div>
467
  </div>
468
 
469
  <div class="mb-3">
 
819
  document.getElementById('prefBudget').textContent = formData.price_range ? formData.price_range.map(range => `₹${range[0]} - ${range[1] ? `₹${range[1]}` : 'Above'}`).join(', ') : 'Any';
820
  document.getElementById('prefFeatures').textContent = formData.features ? formData.features.join(', ') : 'None';
821
 
822
+ // Add phone number input formatting
823
+ document.getElementById('phone').addEventListener('input', function(e) {
824
+ // Remove any non-digit characters
825
+ let value = e.target.value.replace(/\D/g, '');
826
+ // Limit to 10 digits
827
+ if (value.length > 10) {
828
+ value = value.substring(0, 10);
829
+ }
830
+ e.target.value = value;
831
+ });
832
+
833
  // Handle account form submission
834
  document.getElementById('accountForm').addEventListener('submit', async (e) => {
835
  e.preventDefault();
 
837
  const firstName = document.getElementById('firstName').value;
838
  const lastName = document.getElementById('lastName').value;
839
  const email = document.getElementById('email').value;
840
+ let phone = document.getElementById('phone').value;
841
  const password = document.getElementById('password').value;
842
 
843
+ // Clean phone number (remove any remaining non-digits)
844
+ phone = phone.replace(/\D/g, '');
845
+
846
+ // Validate phone number
847
+ if (phone.length !== 10) {
848
+ alert('Please enter a valid 10-digit mobile number.');
849
+ return;
850
+ }
851
+
852
  // Send account details and recommendations to the backend
853
  const accountResponse = await fetch('/create_account_and_send_whatsapp', {
854
  method: 'POST',
 
868
  const result = await accountResponse.json();
869
 
870
  if (result.success) {
871
+ // Show dynamic success message based on what was sent
872
+ let successMessage = 'Account created successfully! ';
873
+ if (result.details) {
874
+ const whatsappSent = result.details.some(detail => detail.includes('WhatsApp message sent successfully'));
875
+ const emailSent = result.details.some(detail => detail.includes('Email sent successfully'));
876
+
877
+ if (whatsappSent && emailSent) {
878
+ successMessage += 'Recommendations sent to your WhatsApp and email!';
879
+ } else if (whatsappSent) {
880
+ successMessage += 'Recommendations sent to your WhatsApp!';
881
+ } else if (emailSent) {
882
+ successMessage += 'Recommendations sent to your email!';
883
+ } else {
884
+ successMessage += 'Account created but there were issues sending messages.';
885
+ }
886
+ } else {
887
+ successMessage += result.message || 'Recommendations sent!';
888
+ }
889
+ alert(successMessage);
890
  displayRecommendations(recommendations);
891
  } else {
892
+ // Show detailed error information
893
+ let errorMessage = 'Failed to create account: ' + (result.error || result.message);
894
+ if (result.details && result.details.length > 0) {
895
+ errorMessage += '\n\nDetails:\n' + result.details.join('\n');
896
+ }
897
+ alert(errorMessage);
898
  }
899
  });
900