From d3be597489c69fdb26e1e32f9207565efc84d0c9 Mon Sep 17 00:00:00 2001 From: RIT Services Date: Fri, 21 Aug 2026 06:08:27 +0000 Subject: [PATCH] assignment mark format --- .env | 3 + db/whatsappbot.mv.db | Bin 40960 -> 36864 bytes pom.xml | 5 + .../controller/WebhookController.java | 25 ++ .../whatsapp/handler/GrievanceHandler.java | 10 +- .../whatsapp/handler/StudentMenuHandler.java | 110 ++++++- .../rit/whatsapp/util/MessageFormatter.java | 309 +++++++++++++++--- src/main/resources/application.properties | 15 +- 8 files changed, 423 insertions(+), 54 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..d312488 --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +DB_URL=jdbc:postgresql://localhost:5432/whatsapp_bot +DB_USERNAME=whatsapp_user +DB_PASSWORD=RITHosting123 diff --git a/db/whatsappbot.mv.db b/db/whatsappbot.mv.db index d10c6e6d9861140099008396e7020691d73891be..770bc98ac2573f5ec0d53c2f2140684911a2475f 100644 GIT binary patch literal 36864 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 literal 40960 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 XAm#rl|IYb;kn{h50RMMSh5!E_ug87X diff --git a/pom.xml b/pom.xml index 11e2628..5376ff9 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,11 @@ h2 runtime + + org.postgresql + postgresql + runtime + com.fasterxml.jackson.core jackson-databind diff --git a/src/main/java/com/rit/whatsapp/controller/WebhookController.java b/src/main/java/com/rit/whatsapp/controller/WebhookController.java index 6e09149..488b28c 100644 --- a/src/main/java/com/rit/whatsapp/controller/WebhookController.java +++ b/src/main/java/com/rit/whatsapp/controller/WebhookController.java @@ -198,11 +198,36 @@ public class WebhookController { return; } + if ("student_show_menu".equals(selectedButtonId)) { + studentMenuHandler.sendStudentMenuDirectly(phoneNumber); + return; + } + if ("student_exam_fees".equals(selectedButtonId)) { studentMenuHandler.handleExamFees(phoneNumber); return; } + if ("student_cat1_marks".equals(selectedButtonId)) { + studentMenuHandler.handleCat1Marks(phoneNumber); + return; + } + + if ("student_cat2_marks".equals(selectedButtonId)) { + studentMenuHandler.handleCat2Marks(phoneNumber); + return; + } + + if ("student_cat3_marks".equals(selectedButtonId)) { + studentMenuHandler.handleCat3Marks(phoneNumber); + return; + } + + if ("student_assignment_marks".equals(selectedButtonId)) { + studentMenuHandler.handleAssignmentMarks(phoneNumber); + return; + } + if ("student_payment_history".equals(selectedButtonId)) { studentMenuHandler.handlePaymentHistory(phoneNumber); return; diff --git a/src/main/java/com/rit/whatsapp/handler/GrievanceHandler.java b/src/main/java/com/rit/whatsapp/handler/GrievanceHandler.java index 5137562..638c5cc 100644 --- a/src/main/java/com/rit/whatsapp/handler/GrievanceHandler.java +++ b/src/main/java/com/rit/whatsapp/handler/GrievanceHandler.java @@ -7,6 +7,8 @@ import com.rit.whatsapp.service.WhatsAppMessageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.context.annotation.Lazy; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -18,11 +20,13 @@ public class GrievanceHandler { private final WhatsAppMessageService messageService; private final SessionService sessionService; + private final StudentMenuHandler studentMenuHandler; @Autowired - public GrievanceHandler(WhatsAppMessageService messageService, SessionService sessionService) { + public GrievanceHandler(WhatsAppMessageService messageService, SessionService sessionService, @Lazy StudentMenuHandler studentMenuHandler) { this.messageService = messageService; this.sessionService = sessionService; + this.studentMenuHandler = studentMenuHandler; } public void startGrievanceFlow(String phoneNumber) { @@ -39,6 +43,7 @@ public class GrievanceHandler { ); messageService.sendInteractiveMessage(phoneNumber, buttonMessage); + studentMenuHandler.sendStudentMenuDirectly(phoneNumber); } public void handleCategorySelection(String phoneNumber, String selectedCategory) { @@ -60,6 +65,9 @@ public class GrievanceHandler { // Reset state back to main menu sessionService.resetState(phoneNumber); + + // Display student menu + studentMenuHandler.sendStudentMenuDirectly(phoneNumber); } private Map createButton(String id, String title) { diff --git a/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java b/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java index d1f1b04..253cb25 100644 --- a/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java +++ b/src/main/java/com/rit/whatsapp/handler/StudentMenuHandler.java @@ -81,22 +81,43 @@ public class StudentMenuHandler { weeklyBtn.put("id", "student_weekly_timetable"); weeklyBtn.put("title", "Weekly Timetable"); buttons.add(weeklyBtn); + + Map menuBtn = new HashMap<>(); + menuBtn.put("id", "student_show_menu"); + menuBtn.put("title", "Student Menu"); + buttons.add(menuBtn); + System.out.println("FINAL TODAY TIMETABLE MESSAGE:\n" + todaySchedule); Map buttonMessage = WhatsAppMessageBuilder.buildButtonMessage(todaySchedule, buttons); messageService.sendInteractiveMessage(phoneNumber, buttonMessage); + sendStudentMenuDirectly(phoneNumber); + break; + + case "student_internal_marks": + sendInternalMarksMenu(phoneNumber); break; - case "student_internal_marks": - String rawCatMarks = imsApiService.getCatMarks(token); - String rawAssignmentMarks = imsApiService.getAssignmentMarks(token); - sendResponseWithMenu(phoneNumber, MessageFormatter.formatInternalMarks(rawCatMarks, rawAssignmentMarks)); + case "student_cat1_marks": + handleCat1Marks(phoneNumber); break; - + + case "student_cat2_marks": + handleCat2Marks(phoneNumber); + break; + + case "student_cat3_marks": + handleCat3Marks(phoneNumber); + break; + + case "student_assignment_marks": + handleAssignmentMarks(phoneNumber); + break; + case "student_semester_results": sendSemesterSelection(phoneNumber, token); break; - + case "student_fee_details": { String rawFees = imsApiService.getFees(token); String bodyText = MessageFormatter.formatAcademicFeesOnly(rawFees); @@ -118,6 +139,7 @@ public class StudentMenuHandler { Map feeButtonMessage = WhatsAppMessageBuilder.buildButtonMessage(bodyText, feeButtons); messageService.sendInteractiveMessage(phoneNumber, feeButtonMessage); + sendStudentMenuDirectly(phoneNumber); break; } @@ -166,6 +188,7 @@ public class StudentMenuHandler { ); messageService.sendInteractiveMessage(phoneNumber, interactiveList); + sendStudentMenuDirectly(phoneNumber); } public void handleSemesterSelection(String phoneNumber, String selectedOptionId) { @@ -312,6 +335,7 @@ public class StudentMenuHandler { "Receipts", formattedHistory, "Download Receipt", receiptRows ); messageService.sendInteractiveMessage(phoneNumber, listMessage); + sendStudentMenuDirectly(phoneNumber); } else { sendResponseWithMenu(phoneNumber, formattedHistory); } @@ -344,6 +368,80 @@ public class StudentMenuHandler { rows ); messageService.sendInteractiveMessage(phoneNumber, interactiveList); + sendStudentMenuDirectly(phoneNumber); + } + + public void sendStudentMenuDirectly(String phoneNumber) { + sessionService.setUserState(phoneNumber, UserState.MAIN_MENU); + + Map interactiveList = WhatsAppMessageBuilder.buildListMessage( + null, + "Select an option from the menu below", + "Student Menu", + getStudentMenuRows() + ); + messageService.sendInteractiveMessage(phoneNumber, interactiveList); + } + + public void sendInternalMarksMenu(String phoneNumber) { + List> rows = new ArrayList<>(); + rows.add(createRow("student_cat1_marks", "CAT 1 Marks", "View CAT 1 (CO1) marks")); + rows.add(createRow("student_cat2_marks", "CAT 2 Marks", "View CAT 2 (CO2) marks")); + rows.add(createRow("student_cat3_marks", "CAT 3 Marks", "View CAT 3 (CO3) marks")); + rows.add(createRow("student_assignment_marks", "Assignment Marks", "View assignments 1-5 marks")); + + Map interactiveList = WhatsAppMessageBuilder.buildListMessage( + "Internal Marks", + "Select which internal marks you want to view:", + "Select Option", + rows + ); + messageService.sendInteractiveMessage(phoneNumber, interactiveList); + sendStudentMenuDirectly(phoneNumber); + } + + public void handleCat1Marks(String phoneNumber) { + String token = sessionService.getImsToken(phoneNumber); + if (token == null) { + messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again."); + return; + } + String rawCatMarks = imsApiService.getCatMarks(token); + String formatted = com.rit.whatsapp.util.MessageFormatter.formatCat1Marks(rawCatMarks); + sendResponseWithMenu(phoneNumber, formatted); + } + + public void handleCat2Marks(String phoneNumber) { + String token = sessionService.getImsToken(phoneNumber); + if (token == null) { + messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again."); + return; + } + String rawCatMarks = imsApiService.getCatMarks(token); + String formatted = com.rit.whatsapp.util.MessageFormatter.formatCat2Marks(rawCatMarks); + sendResponseWithMenu(phoneNumber, formatted); + } + + public void handleCat3Marks(String phoneNumber) { + String token = sessionService.getImsToken(phoneNumber); + if (token == null) { + messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again."); + return; + } + String rawCatMarks = imsApiService.getCatMarks(token); + String formatted = com.rit.whatsapp.util.MessageFormatter.formatCat3Marks(rawCatMarks); + sendResponseWithMenu(phoneNumber, formatted); + } + + public void handleAssignmentMarks(String phoneNumber) { + String token = sessionService.getImsToken(phoneNumber); + if (token == null) { + messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again."); + return; + } + String rawAssignmentMarks = imsApiService.getAssignmentMarks(token); + String formatted = com.rit.whatsapp.util.MessageFormatter.formatAssignmentMarks(rawAssignmentMarks); + sendResponseWithMenu(phoneNumber, formatted); } private List> getStudentMenuRows() { diff --git a/src/main/java/com/rit/whatsapp/util/MessageFormatter.java b/src/main/java/com/rit/whatsapp/util/MessageFormatter.java index 8a05ffa..d97070e 100644 --- a/src/main/java/com/rit/whatsapp/util/MessageFormatter.java +++ b/src/main/java/com/rit/whatsapp/util/MessageFormatter.java @@ -287,10 +287,10 @@ public class MessageFormatter { public static String formatInternalMarks(String rawCatJson, String rawAssignmentJson) { StringBuilder sb = new StringBuilder(); - sb.append("\ud83d\udcc8 *Internal Marks*\n\n"); + sb.append("📈 *INTERNAL MARKS REPORT*\n\n"); // --- Parse CAT Marks --- - sb.append("*CAT MARKS:*\n"); + sb.append("✴️ *CAT MARKS:*\n"); if (rawCatJson == null) { sb.append("❌ Failed to retrieve CAT marks.\n\n"); } else { @@ -309,39 +309,52 @@ public class MessageFormatter { if (targetArray != null && targetArray.size() > 0) { for (JsonNode subject : targetArray) { + String code = subject.has("code") ? subject.get("code").asText() : ""; String name = subject.has("name") ? subject.get("name").asText() : - (subject.has("course_name") ? subject.get("course_name").asText() : "Unknown"); + (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); + String co1 = subject.has("co1") ? subject.get("co1").asText().trim() : ""; + String co2 = subject.has("co2") ? subject.get("co2").asText().trim() : ""; + String total = subject.has("total") ? subject.get("total").asText().trim() : ""; + String weightage = subject.has("weightage") ? subject.get("weightage").asText().trim() : ""; - String marks = ""; - if (subject.has("total") && !subject.get("total").asText().isEmpty()) { - marks = subject.get("total").asText(); - if (subject.has("weightage") && !subject.get("weightage").asText().isEmpty()) { - marks += " (" + subject.get("weightage").asText() + " wt)"; - } - } else if (subject.has("marks")) { - marks = subject.get("marks").asText(); + sb.append("📚 *").append(name).append("*"); + if (!code.isEmpty()) { + sb.append(" (").append(code).append(")"); + } + sb.append("\n"); + + if (!co1.isEmpty() || !co2.isEmpty()) { + sb.append(" ├─ "); + if (!co1.isEmpty()) sb.append("CO1: ").append(co1); + if (!co1.isEmpty() && !co2.isEmpty()) sb.append(" | "); + if (!co2.isEmpty()) sb.append("CO2: ").append(co2); + sb.append("\n"); + sb.append(" └─ "); } else { - marks = "N/A"; + sb.append(" └─ "); } - sb.append("- *").append(name).append("*: ").append(marks).append("\n"); + sb.append("*Total*: *").append(total.isEmpty() ? "N/A" : total).append("*"); + if (!weightage.isEmpty()) { + sb.append(" (").append(weightage).append(" wt)"); + } + sb.append("\n\n"); foundData = true; } } if (!foundData) { - sb.append("Details not available in this format.\n"); - sb.append("\n*DEBUG RAW CAT JSON:*\n").append(rawCatJson).append("\n"); + sb.append("Details not available in this format.\n\n"); } } catch (Exception e) { - sb.append("⚠️ Error formatting CAT marks.\nRAW JSON: ").append(rawCatJson).append("\n"); + sb.append("⚠️ Error formatting CAT marks.\n\n"); } } - sb.append("\n"); + sb.append("───────────────\n\n"); // --- Parse Assignment Marks --- - sb.append("*ASSIGNMENT MARKS:*\n"); + sb.append("📋 *ASSIGNMENT MARKS:*\n"); if (rawAssignmentJson == null) { sb.append("❌ Failed to retrieve Assignment marks.\n"); } else { @@ -360,38 +373,256 @@ public class MessageFormatter { if (targetArray != null && targetArray.size() > 0) { for (JsonNode subject : targetArray) { + String code = subject.has("code") ? subject.get("code").asText() : ""; String name = subject.has("name") ? subject.get("name").asText() : - (subject.has("course_name") ? subject.get("course_name").asText() : "Unknown"); + (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); + String a1 = subject.has("a1") ? subject.get("a1").asText().trim() : ""; + String a2 = subject.has("a2") ? subject.get("a2").asText().trim() : ""; + String a3 = subject.has("a3") ? subject.get("a3").asText().trim() : ""; + String a4 = subject.has("a4") ? subject.get("a4").asText().trim() : ""; + String a5 = subject.has("a5") ? subject.get("a5").asText().trim() : ""; + String total = subject.has("total") ? subject.get("total").asText().trim() : ""; - String marks = ""; - if (subject.has("total") && !subject.get("total").asText().isEmpty()) { - marks = subject.get("total").asText(); - if (subject.has("weightage") && !subject.get("weightage").asText().isEmpty()) { - marks += " (" + subject.get("weightage").asText() + " wt)"; - } - } else if (subject.has("marks")) { - marks = subject.get("marks").asText(); + sb.append("📝 *").append(name).append("*"); + if (!code.isEmpty()) { + sb.append(" (").append(code).append(")"); + } + sb.append("\n"); + + java.util.List assignList = new java.util.ArrayList<>(); + if (!a1.isEmpty()) assignList.add("A1: " + a1); + if (!a2.isEmpty()) assignList.add("A2: " + a2); + if (!a3.isEmpty()) assignList.add("A3: " + a3); + if (!a4.isEmpty()) assignList.add("A4: " + a4); + if (!a5.isEmpty()) assignList.add("A5: " + a5); + + if (!assignList.isEmpty()) { + sb.append(" ├─ ").append(String.join(" | ", assignList)).append("\n"); + sb.append(" └─ "); } else { - marks = "N/A"; + sb.append(" └─ "); } - sb.append("- *").append(name).append("*: ").append(marks).append("\n"); + sb.append("*Total*: *").append(total.isEmpty() ? "N/A" : total).append("*\n\n"); foundData = true; } } if (!foundData) { sb.append("Details not available in this format.\n"); - sb.append("\n*DEBUG RAW ASSIGNMENT JSON:*\n").append(rawAssignmentJson).append("\n"); } } catch (Exception e) { - sb.append("⚠️ Error formatting Assignment marks.\nRAW JSON: ").append(rawAssignmentJson).append("\n"); + sb.append("⚠️ Error formatting Assignment marks.\n"); } } return sb.toString(); } + public static String formatCat1Marks(String rawCatJson) { + StringBuilder sb = new StringBuilder(); + sb.append("📈 *CAT 1 MARKS REPORT*\n\n"); + if (rawCatJson == null) { + sb.append("❌ Failed to retrieve CAT 1 marks.\n\n"); + } else { + try { + JsonNode root = mapper.readTree(rawCatJson); + boolean foundData = false; + + JsonNode targetArray = null; + if (root.has("data")) { + if (root.get("data").isArray()) { + targetArray = root.get("data"); + } else if (root.get("data").isObject() && root.get("data").has("subjects") && root.get("data").get("subjects").isArray()) { + targetArray = root.get("data").get("subjects"); + } + } + + if (targetArray != null && targetArray.size() > 0) { + for (JsonNode subject : targetArray) { + String code = subject.has("code") ? subject.get("code").asText() : ""; + String name = subject.has("name") ? subject.get("name").asText() : + (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); + String co1 = subject.has("co1") ? subject.get("co1").asText().trim() : ""; + + sb.append("📚 *").append(name).append("*"); + if (!code.isEmpty()) { + sb.append(" (").append(code).append(")"); + } + sb.append("\n"); + sb.append(" └─ *CAT 1 (CO1)*: *").append(co1.isEmpty() ? "N/A" : co1).append("*\n\n"); + foundData = true; + } + } + + if (!foundData) { + sb.append("Details not available in this format.\n\n"); + } + } catch (Exception e) { + sb.append("⚠️ Error formatting CAT 1 marks.\n\n"); + } + } + return sb.toString(); + } + + public static String formatCat2Marks(String rawCatJson) { + StringBuilder sb = new StringBuilder(); + sb.append("📈 *CAT 2 MARKS REPORT*\n\n"); + if (rawCatJson == null) { + sb.append("❌ Failed to retrieve CAT 2 marks.\n\n"); + } else { + try { + JsonNode root = mapper.readTree(rawCatJson); + boolean foundData = false; + + JsonNode targetArray = null; + if (root.has("data")) { + if (root.get("data").isArray()) { + targetArray = root.get("data"); + } else if (root.get("data").isObject() && root.get("data").has("subjects") && root.get("data").get("subjects").isArray()) { + targetArray = root.get("data").get("subjects"); + } + } + + if (targetArray != null && targetArray.size() > 0) { + for (JsonNode subject : targetArray) { + String code = subject.has("code") ? subject.get("code").asText() : ""; + String name = subject.has("name") ? subject.get("name").asText() : + (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); + String co2 = subject.has("co2") ? subject.get("co2").asText().trim() : ""; + + sb.append("📚 *").append(name).append("*"); + if (!code.isEmpty()) { + sb.append(" (").append(code).append(")"); + } + sb.append("\n"); + sb.append(" └─ *CAT 2 (CO2)*: *").append(co2.isEmpty() ? "N/A" : co2).append("*\n\n"); + foundData = true; + } + } + + if (!foundData) { + sb.append("Details not available in this format.\n\n"); + } + } catch (Exception e) { + sb.append("⚠️ Error formatting CAT 2 marks.\n\n"); + } + } + return sb.toString(); + } + + public static String formatCat3Marks(String rawCatJson) { + StringBuilder sb = new StringBuilder(); + sb.append("📈 *CAT 3 MARKS REPORT*\n\n"); + if (rawCatJson == null) { + sb.append("❌ Failed to retrieve CAT 3 marks.\n\n"); + } else { + try { + JsonNode root = mapper.readTree(rawCatJson); + boolean foundData = false; + + JsonNode targetArray = null; + if (root.has("data")) { + if (root.get("data").isArray()) { + targetArray = root.get("data"); + } else if (root.get("data").isObject() && root.get("data").has("subjects") && root.get("data").get("subjects").isArray()) { + targetArray = root.get("data").get("subjects"); + } + } + + if (targetArray != null && targetArray.size() > 0) { + for (JsonNode subject : targetArray) { + String code = subject.has("code") ? subject.get("code").asText() : ""; + String name = subject.has("name") ? subject.get("name").asText() : + (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); + String co3 = subject.has("co3") ? subject.get("co3").asText().trim() : ""; + + sb.append("📚 *").append(name).append("*"); + if (!code.isEmpty()) { + sb.append(" (").append(code).append(")"); + } + sb.append("\n"); + sb.append(" └─ *CAT 3 (CO3)*: *").append(co3.isEmpty() ? "N/A" : co3).append("*\n\n"); + foundData = true; + } + } + + if (!foundData) { + sb.append("Details not available in this format.\n\n"); + } + } catch (Exception e) { + sb.append("⚠️ Error formatting CAT 3 marks.\n\n"); + } + } + return sb.toString(); + } + + public static String formatAssignmentMarks(String rawAssignmentJson) { + StringBuilder sb = new StringBuilder(); + sb.append("📋 *ASSIGNMENT MARKS:*\n\n"); + if (rawAssignmentJson == null) { + sb.append("❌ Failed to retrieve Assignment marks.\n"); + } else { + try { + JsonNode root = mapper.readTree(rawAssignmentJson); + boolean foundData = false; + + JsonNode targetArray = null; + if (root.has("data")) { + if (root.get("data").isArray()) { + targetArray = root.get("data"); + } else if (root.get("data").isObject() && root.get("data").has("subjects") && root.get("data").get("subjects").isArray()) { + targetArray = root.get("data").get("subjects"); + } + } + + if (targetArray != null && targetArray.size() > 0) { + for (JsonNode subject : targetArray) { + String code = subject.has("code") ? subject.get("code").asText() : ""; + String name = subject.has("name") ? subject.get("name").asText() : + (subject.has("course_name") ? subject.get("course_name").asText() : "Subject"); + String a1 = subject.has("a1") ? subject.get("a1").asText().trim() : ""; + String a2 = subject.has("a2") ? subject.get("a2").asText().trim() : ""; + String a3 = subject.has("a3") ? subject.get("a3").asText().trim() : ""; + String a4 = subject.has("a4") ? subject.get("a4").asText().trim() : ""; + String a5 = subject.has("a5") ? subject.get("a5").asText().trim() : ""; + String total = subject.has("total") ? subject.get("total").asText().trim() : ""; + + sb.append("📝 *").append(name).append("*"); + if (!code.isEmpty()) { + sb.append(" (").append(code).append(")"); + } + sb.append("\n"); + + java.util.List assignList = new java.util.ArrayList<>(); + if (!a1.isEmpty()) assignList.add("A1: " + a1); + if (!a2.isEmpty()) assignList.add("A2: " + a2); + if (!a3.isEmpty()) assignList.add("A3: " + a3); + if (!a4.isEmpty()) assignList.add("A4: " + a4); + if (!a5.isEmpty()) assignList.add("A5: " + a5); + + if (!assignList.isEmpty()) { + sb.append(" ├─ ").append(String.join(" | ", assignList)).append("\n"); + sb.append(" └─ "); + } else { + sb.append(" └─ "); + } + + sb.append("*Total*: *").append(total.isEmpty() ? "N/A" : total).append("*\n\n"); + foundData = true; + } + } + + if (!foundData) { + sb.append("Details not available in this format.\n"); + } + } catch (Exception e) { + sb.append("⚠️ Error formatting Assignment marks.\n"); + } + } + return sb.toString(); + } + public static String formatFeesAndExamFees(String rawFees, String rawExamFees) { StringBuilder sb = new StringBuilder(); @@ -898,7 +1129,9 @@ public class MessageFormatter { if (schedule.has(day)) { JsonNode daySchedule = schedule.get(day); - sb.append(label).append("\n"); + StringBuilder daySb = new StringBuilder(); + daySb.append("📅 *").append(label).append("*\n"); + boolean dayHasClasses = false; int maxPeriod = 7; java.util.Iterator fieldNames = daySchedule.fieldNames(); @@ -913,7 +1146,6 @@ public class MessageFormatter { for (int period = 1; period <= maxPeriod; period++) { String periodKey = String.valueOf(period); - sb.append(getNumberEmoji(period)).append(" "); if (daySchedule.has(periodKey)) { JsonNode details = daySchedule.get(periodKey); @@ -940,16 +1172,15 @@ public class MessageFormatter { } if (!subjects.isEmpty()) { - sb.append(String.join(" / ", subjects)).append("\n"); + daySb.append(" ").append(getNumberEmoji(period)).append(" ").append(String.join(" / ", subjects)).append("\n"); + dayHasClasses = true; hasAnyClasses = true; - } else { - sb.append("—\n"); } - } else { - sb.append("—\n"); } } - sb.append("\n"); + if (dayHasClasses) { + sb.append(daySb).append("\n"); + } } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index fef27b8..69fd92f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -8,15 +8,14 @@ whatsapp.verify-token=rit_bot_secret_token_123 # WhatsApp Phone Number ID (You get this from the Meta developer console) whatsapp.phone-number-id=1236658909534007 -# H2 Database Configuration -spring.datasource.url=jdbc:h2:file:./db/whatsappbot -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=password -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +# PostgreSQL Database Configuration +spring.datasource.url=${DB_URL} +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.username=${DB_USERNAME} +spring.datasource.password=${DB_PASSWORD} +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect spring.jpa.hibernate.ddl-auto=update -spring.h2.console.enabled=true # Encryption Secret for Passcodes (Must be 16, 24, or 32 bytes) bot.encryption.secret=12345678901234567890123456789012 -whatsapp.api-token=EAAc3Wjql00oBSfSg58drijkqefLn47aI2vYcl8r6GxuwC5vJRt2G8Std3ynf3KnKp9SyuwKXAQfr2Q7hYrNOE66t3dRcS3GAWFbDbikrmvXkbjpIh5V9QNVGI2T4V1VeJAj9d6HMsiHZCAJujaIVLdLleIPti4ok9brnNf1BPwBZA8SZAQ06OUcbSba3SZAQhcoFsh1Utz1g9PLCqsl8Fh9H8ynVJagAxMYqF86sV7fEHKpG6eCp2EkRtfOoE7XbL5AurGkiZA5ZBHiSZCOOujplm3cmgZDZD +whatsapp.api-token=EAAc3Wjql00oBSWGWTlmDkMegzpdfKYWqNp0jci6efxyhHArM0371vc3t8XEZA74jgy6reRpS0XTwH1qUSoiJ5t1KjlX3PpY2fUVa1zAaWBDq0FB5YG6ll20pSfZBHHcvAABIweGSkWDY4Oe2znY76JWSlPpD0LXORdiRTZChu1uTMOMSgUxGdaQTiJJzxkVovCrK6jzocjGzwZCCLKAKyxKqLMECDfwgnrxaTqwloQ7oZA1X1ZCstFvPfGQ32LJ59SBeGzTuC3PM8GewZB6uvYiKSuGEAZDZD