504 lines
22 KiB
Java
504 lines
22 KiB
Java
package com.rit.whatsapp.handler;
|
|
|
|
import com.rit.whatsapp.model.UserState;
|
|
import com.rit.whatsapp.service.ImsApiService;
|
|
import com.rit.whatsapp.service.SessionService;
|
|
import com.rit.whatsapp.service.WhatsAppMessageBuilder;
|
|
import com.rit.whatsapp.service.WhatsAppMessageService;
|
|
import com.rit.whatsapp.util.MessageFormatter;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Component;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
@Component
|
|
public class StudentMenuHandler {
|
|
|
|
private final WhatsAppMessageService messageService;
|
|
private final SessionService sessionService;
|
|
private final GrievanceHandler grievanceHandler;
|
|
private final ImsApiService imsApiService;
|
|
|
|
@Autowired
|
|
public StudentMenuHandler(WhatsAppMessageService messageService,
|
|
SessionService sessionService,
|
|
GrievanceHandler grievanceHandler,
|
|
ImsApiService imsApiService) {
|
|
this.messageService = messageService;
|
|
this.sessionService = sessionService;
|
|
this.grievanceHandler = grievanceHandler;
|
|
this.imsApiService = imsApiService;
|
|
}
|
|
|
|
public void sendMainMenu(String phoneNumber) {
|
|
sessionService.setUserState(phoneNumber, UserState.MAIN_MENU);
|
|
|
|
String token = sessionService.getImsToken(phoneNumber);
|
|
String studentName = "Student";
|
|
if (token != null) {
|
|
studentName = sessionService.getStudentName(phoneNumber, token);
|
|
}
|
|
|
|
Map<String, Object> interactiveList = WhatsAppMessageBuilder.buildListMessage(
|
|
"RIT Digital Assistant",
|
|
"Welcome " + studentName + "! Please select an option from the menu below.",
|
|
"Student Menu",
|
|
getStudentMenuRows()
|
|
);
|
|
|
|
messageService.sendInteractiveMessage(phoneNumber, interactiveList);
|
|
}
|
|
|
|
|
|
public void handleMenuSelection(String phoneNumber, String selectedOptionId) {
|
|
String token = sessionService.getImsToken(phoneNumber);
|
|
if (token == null) {
|
|
messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again.");
|
|
return;
|
|
}
|
|
|
|
switch (selectedOptionId) {
|
|
case "student_attendance":
|
|
String rawAttendance = imsApiService.getAttendance(token);
|
|
String rawLeaves = imsApiService.getLeaves(token);
|
|
sendResponseWithMenu(phoneNumber, MessageFormatter.formatAttendanceAndLeaves(rawAttendance, rawLeaves));
|
|
break;
|
|
|
|
case "student_timetable":
|
|
sendTimetableMenu(phoneNumber, token);
|
|
break;
|
|
|
|
case "student_internal_marks":
|
|
sendInternalMarksMenu(phoneNumber);
|
|
break;
|
|
|
|
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":
|
|
sendFeeDetailsMenu(phoneNumber, token);
|
|
break;
|
|
|
|
case "student_raise_grievance":
|
|
grievanceHandler.startGrievanceFlow(phoneNumber);
|
|
break;
|
|
|
|
case "student_help_menu":
|
|
sendHelpMenu(phoneNumber);
|
|
break;
|
|
|
|
case "student_logout":
|
|
sessionService.logoutUser(phoneNumber);
|
|
messageService.sendMessage(phoneNumber, "You have been logged out successfully. Type 'Hi' to log in again.");
|
|
break;
|
|
|
|
case "student_contact_department":
|
|
messageService.sendMessage(phoneNumber, "❌ No such Faculty mentor is assigned.");
|
|
sendMainMenu(phoneNumber);
|
|
break;
|
|
|
|
case "student_academic_calendar":
|
|
messageService.sendMessage(phoneNumber, "❌ Academic calendar is not updated yet.");
|
|
sendMainMenu(phoneNumber);
|
|
break;
|
|
|
|
case "student_exam_schedule":
|
|
messageService.sendMessage(phoneNumber, "❌ Exam schedule is not updated yet.");
|
|
sendMainMenu(phoneNumber);
|
|
break;
|
|
|
|
case "student_circulars":
|
|
messageService.sendMessage(phoneNumber, "❌ Circulars & Notices are not updated yet.");
|
|
sendMainMenu(phoneNumber);
|
|
break;
|
|
|
|
default:
|
|
messageService.sendMessage(phoneNumber, "❌ Details are not updated yet.");
|
|
sendMainMenu(phoneNumber);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void sendSemesterSelection(String phoneNumber, String token) {
|
|
sessionService.setUserState(phoneNumber, UserState.AWAITING_SEMESTER_SELECTION);
|
|
|
|
List<Map<String, String>> rows = new ArrayList<>();
|
|
for (int i = 1; i <= 8; i++) {
|
|
rows.add(createRow("sem_" + i, "Semester " + i, ""));
|
|
}
|
|
|
|
String rawDashboard = imsApiService.getDashboard(token);
|
|
String bodyText = MessageFormatter.formatDashboardCgpa(rawDashboard);
|
|
|
|
Map<String, Object> interactiveList = WhatsAppMessageBuilder.buildListMessage(
|
|
"Semester Results",
|
|
bodyText,
|
|
"Select Semester",
|
|
rows
|
|
);
|
|
|
|
messageService.sendInteractiveMessage(phoneNumber, interactiveList);
|
|
sendStudentMenuDirectly(phoneNumber);
|
|
}
|
|
|
|
public void handleSemesterSelection(String phoneNumber, String selectedOptionId) {
|
|
String token = sessionService.getImsToken(phoneNumber);
|
|
if (token == null) {
|
|
messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again.");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
int semester = Integer.parseInt(selectedOptionId.replace("sem_", ""));
|
|
byte[] pdfBytes = imsApiService.getResultsPdf(token, semester);
|
|
|
|
if (pdfBytes != null) {
|
|
String fileName = "Semester_" + semester + "_Results.pdf";
|
|
String mediaId = messageService.uploadMedia(pdfBytes, fileName, "application/pdf");
|
|
|
|
if (mediaId != null) {
|
|
messageService.sendDocumentMessage(phoneNumber, mediaId, "Here are your Semester " + semester + " results!", fileName);
|
|
sendSemesterSelection(phoneNumber, token);
|
|
} else {
|
|
messageService.sendMessage(phoneNumber, "Failed to upload the results document to WhatsApp.");
|
|
sendSemesterSelection(phoneNumber, token);
|
|
}
|
|
} else {
|
|
messageService.sendMessage(phoneNumber, "Failed to download your results. They may not be published yet.");
|
|
sendSemesterSelection(phoneNumber, token);
|
|
}
|
|
} catch (Exception e) {
|
|
messageService.sendMessage(phoneNumber, "Invalid semester selected.");
|
|
sendSemesterSelection(phoneNumber, token);
|
|
}
|
|
|
|
sessionService.resetState(phoneNumber); // Reset state after fetching results
|
|
}
|
|
|
|
public void handleReceiptSelection(String phoneNumber, String selectedOptionId) {
|
|
String token = sessionService.getImsToken(phoneNumber);
|
|
if (token == null) {
|
|
messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again.");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
byte[] pdfBytes = null;
|
|
String fileName = "Receipt.pdf";
|
|
String docMessage = "Here is your Fee Receipt!";
|
|
|
|
if (selectedOptionId.startsWith("exam_")) {
|
|
String longId = sessionService.getReceiptIdMapping(phoneNumber, selectedOptionId);
|
|
pdfBytes = imsApiService.getExamFeeReceiptPdf(token, longId);
|
|
fileName = "Exam_Receipt.pdf";
|
|
docMessage = "Here is your Exam Fee Receipt!";
|
|
} else if (selectedOptionId.startsWith("acad_")) {
|
|
String longId = sessionService.getReceiptIdMapping(phoneNumber, selectedOptionId);
|
|
pdfBytes = imsApiService.getAcademicFeeReceiptPdf(token, longId);
|
|
fileName = "Academic_Receipt.pdf";
|
|
docMessage = "Here is your Academic Fee Receipt!";
|
|
} else if (selectedOptionId.startsWith("cons_")) {
|
|
String longId = sessionService.getReceiptIdMapping(phoneNumber, selectedOptionId);
|
|
pdfBytes = imsApiService.getConsolidatedAcademicFeeReceiptPdf(token, longId);
|
|
fileName = "Consolidated_Receipt.pdf";
|
|
docMessage = "Here is your Consolidated Academic Fee Receipt!";
|
|
}
|
|
|
|
if (pdfBytes != null) {
|
|
String mediaId = messageService.uploadMedia(pdfBytes, fileName, "application/pdf");
|
|
if (mediaId != null) {
|
|
messageService.sendDocumentMessage(phoneNumber, mediaId, docMessage, fileName);
|
|
sendPaymentHistoryMenu(phoneNumber, token);
|
|
} else {
|
|
messageService.sendMessage(phoneNumber, "Failed to upload the receipt document to WhatsApp.");
|
|
sendPaymentHistoryMenu(phoneNumber, token);
|
|
}
|
|
} else {
|
|
messageService.sendMessage(phoneNumber, "Failed to download your receipt. It may not be available.");
|
|
sendPaymentHistoryMenu(phoneNumber, token);
|
|
}
|
|
} catch (Exception e) {
|
|
messageService.sendMessage(phoneNumber, "Invalid receipt selected.");
|
|
sendPaymentHistoryMenu(phoneNumber, token);
|
|
}
|
|
|
|
sessionService.resetState(phoneNumber); // Reset state after fetching receipt
|
|
}
|
|
|
|
public void handleWeeklyTimetable(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 rawTimetable = imsApiService.getTimetable(token);
|
|
String weeklyTimetable = MessageFormatter.formatWeeklyTimetable(rawTimetable);
|
|
|
|
// Send weekly timetable as standard message (up to 4096 characters limit)
|
|
messageService.sendMessage(phoneNumber, weeklyTimetable);
|
|
|
|
// Follow up with Timetable sub-menu again
|
|
sendTimetableMenu(phoneNumber, token);
|
|
}
|
|
|
|
public void handleExamFees(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 rawExamFees = imsApiService.getExamFees(token);
|
|
String formattedExamFees = MessageFormatter.formatExamFees(rawExamFees);
|
|
messageService.sendMessage(phoneNumber, formattedExamFees);
|
|
sendFeeDetailsMenu(phoneNumber, token);
|
|
}
|
|
|
|
public void handlePaymentHistory(String phoneNumber) {
|
|
String token = sessionService.getImsToken(phoneNumber);
|
|
if (token == null) {
|
|
messageService.sendMessage(phoneNumber, "Your session has expired. Please type 'Reset' to login again.");
|
|
return;
|
|
}
|
|
sendPaymentHistoryMenu(phoneNumber, token);
|
|
}
|
|
|
|
public void sendTimetableMenu(String phoneNumber, String token) {
|
|
String rawTimetable = imsApiService.getTimetable(token);
|
|
String todaySchedule = MessageFormatter.formatTimetable(rawTimetable);
|
|
|
|
// Truncate to stay safely within WhatsApp 1024 character limit for button bodies
|
|
if (todaySchedule.length() > 1020) {
|
|
todaySchedule = todaySchedule.substring(0, 1017) + "...";
|
|
}
|
|
|
|
List<Map<String, String>> buttons = new ArrayList<>();
|
|
Map<String, String> weeklyBtn = new HashMap<>();
|
|
weeklyBtn.put("id", "student_weekly_timetable");
|
|
weeklyBtn.put("title", "Weekly Timetable");
|
|
buttons.add(weeklyBtn);
|
|
|
|
Map<String, String> 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<String, Object> buttonMessage = WhatsAppMessageBuilder.buildButtonMessage(todaySchedule, buttons);
|
|
messageService.sendInteractiveMessage(phoneNumber, buttonMessage);
|
|
sendStudentMenuDirectly(phoneNumber);
|
|
}
|
|
|
|
public void sendFeeDetailsMenu(String phoneNumber, String token) {
|
|
String rawFees = imsApiService.getFees(token);
|
|
String bodyText = MessageFormatter.formatAcademicFeesOnly(rawFees);
|
|
|
|
List<Map<String, String>> feeButtons = new ArrayList<>();
|
|
Map<String, String> examBtn = new HashMap<>();
|
|
examBtn.put("id", "student_exam_fees");
|
|
examBtn.put("title", "Exam Fees");
|
|
feeButtons.add(examBtn);
|
|
|
|
Map<String, String> historyBtn = new HashMap<>();
|
|
historyBtn.put("id", "student_payment_history");
|
|
historyBtn.put("title", "Payment History");
|
|
feeButtons.add(historyBtn);
|
|
|
|
if (bodyText.length() > 1020) {
|
|
bodyText = bodyText.substring(0, 1017) + "...";
|
|
}
|
|
|
|
Map<String, Object> feeButtonMessage = WhatsAppMessageBuilder.buildButtonMessage(bodyText, feeButtons);
|
|
messageService.sendInteractiveMessage(phoneNumber, feeButtonMessage);
|
|
sendStudentMenuDirectly(phoneNumber);
|
|
}
|
|
|
|
public void sendPaymentHistoryMenu(String phoneNumber, String token) {
|
|
String rawExamFees = imsApiService.getExamFees(token);
|
|
String rawFeesHistory = imsApiService.getAcademicFeesHistory(token);
|
|
|
|
String formattedHistory = MessageFormatter.formatCombinedPaymentHistory(rawExamFees, rawFeesHistory);
|
|
|
|
Map<String, String> idMappings = new HashMap<>();
|
|
List<Map<String, String>> examRows = MessageFormatter.extractReceiptRows(rawExamFees, idMappings);
|
|
List<Map<String, String>> acadRows = MessageFormatter.extractAcademicReceiptRows(rawFeesHistory, idMappings);
|
|
List<Map<String, String>> consRows = MessageFormatter.extractConsolidatedReceiptRows(rawFeesHistory, idMappings);
|
|
|
|
sessionService.storeReceiptIdMappings(phoneNumber, idMappings);
|
|
|
|
List<Map<String, String>> receiptRows = new ArrayList<>();
|
|
receiptRows.addAll(examRows);
|
|
receiptRows.addAll(acadRows);
|
|
receiptRows.addAll(consRows);
|
|
|
|
if (!receiptRows.isEmpty()) {
|
|
if (receiptRows.size() > 10) receiptRows = receiptRows.subList(0, 10);
|
|
sessionService.setUserState(phoneNumber, UserState.AWAITING_RECEIPT_SELECTION);
|
|
|
|
if (formattedHistory.length() > 1024) {
|
|
formattedHistory = formattedHistory.substring(0, 1021) + "...";
|
|
}
|
|
|
|
Map<String, Object> listMessage = WhatsAppMessageBuilder.buildListMessage(
|
|
"Receipts", formattedHistory, "Download Receipt", receiptRows
|
|
);
|
|
messageService.sendInteractiveMessage(phoneNumber, listMessage);
|
|
sendStudentMenuDirectly(phoneNumber);
|
|
} else {
|
|
sendResponseWithMenu(phoneNumber, formattedHistory);
|
|
}
|
|
}
|
|
|
|
private void sendResponseWithMenu(String phoneNumber, String bodyText) {
|
|
// Meta API interactive list body limit is 1024 characters
|
|
if (bodyText.length() > 1024) {
|
|
bodyText = bodyText.substring(0, 1021) + "...";
|
|
}
|
|
|
|
Map<String, Object> interactiveList = WhatsAppMessageBuilder.buildListMessage(
|
|
null,
|
|
bodyText,
|
|
"Student Menu",
|
|
getStudentMenuRows()
|
|
);
|
|
messageService.sendInteractiveMessage(phoneNumber, interactiveList);
|
|
}
|
|
|
|
public void sendHelpMenu(String phoneNumber) {
|
|
List<Map<String, String>> rows = new ArrayList<>();
|
|
rows.add(createRow("student_contact_department", "Contact department", "Faculty mentor, HOD, etc."));
|
|
rows.add(createRow("student_logout", "Logout", "Sign out of your account"));
|
|
|
|
Map<String, Object> interactiveList = WhatsAppMessageBuilder.buildListMessage(
|
|
"Help & Settings",
|
|
"Please select an option below:",
|
|
"Help Menu",
|
|
rows
|
|
);
|
|
messageService.sendInteractiveMessage(phoneNumber, interactiveList);
|
|
sendStudentMenuDirectly(phoneNumber);
|
|
}
|
|
|
|
public void sendStudentMenuDirectly(String phoneNumber) {
|
|
sessionService.setUserState(phoneNumber, UserState.MAIN_MENU);
|
|
|
|
Map<String, Object> interactiveList = WhatsAppMessageBuilder.buildListMessage(
|
|
null,
|
|
"Select an option from the menu below",
|
|
"Student Menu",
|
|
getStudentMenuRows()
|
|
);
|
|
messageService.sendInteractiveMessage(phoneNumber, interactiveList);
|
|
}
|
|
|
|
public void sendInternalMarksMenu(String phoneNumber) {
|
|
List<Map<String, String>> rows = new ArrayList<>();
|
|
rows.add(createRow("student_cat1_marks", "CAT 1 Marks", "View CAT 1 (CO1 & CO2) marks"));
|
|
rows.add(createRow("student_cat2_marks", "CAT 2 Marks", "View CAT 2 (CO3) marks"));
|
|
rows.add(createRow("student_cat3_marks", "CAT 3 Marks", "View CAT 3 (CO4 & CO5) marks"));
|
|
rows.add(createRow("student_assignment_marks", "Assignment Marks", "View assignments 1-5 marks"));
|
|
|
|
Map<String, Object> 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);
|
|
messageService.sendMessage(phoneNumber, formatted);
|
|
sendInternalMarksMenu(phoneNumber);
|
|
}
|
|
|
|
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);
|
|
messageService.sendMessage(phoneNumber, formatted);
|
|
sendInternalMarksMenu(phoneNumber);
|
|
}
|
|
|
|
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);
|
|
messageService.sendMessage(phoneNumber, formatted);
|
|
sendInternalMarksMenu(phoneNumber);
|
|
}
|
|
|
|
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);
|
|
messageService.sendMessage(phoneNumber, formatted);
|
|
sendInternalMarksMenu(phoneNumber);
|
|
}
|
|
|
|
private List<Map<String, String>> getStudentMenuRows() {
|
|
List<Map<String, String>> rows = new ArrayList<>();
|
|
rows.add(createRow("student_attendance", "Attendance", "Overall % and Subject-wise"));
|
|
rows.add(createRow("student_timetable", "Timetable", "Today's classes and Weekly"));
|
|
rows.add(createRow("student_internal_marks", "Internal marks", "CAT 1, CAT 2, Overall"));
|
|
rows.add(createRow("student_semester_results", "Semester results", "Latest result and CGPA"));
|
|
rows.add(createRow("student_fee_details", "Fee details & receipt", "Fee paid, Pending, Due date"));
|
|
rows.add(createRow("student_academic_calendar", "Academic calendar", "Holidays and Important dates"));
|
|
rows.add(createRow("student_exam_schedule", "Exam schedule", "Upcoming exams and Hall details"));
|
|
rows.add(createRow("student_circulars", "Circulars & Notices", "Department circulars"));
|
|
rows.add(createRow("student_raise_grievance", "Raise a grievance \u2B50", "Submit an issue ticket"));
|
|
rows.add(createRow("student_help_menu", "Help & Settings", "Logout, Contact dept, etc."));
|
|
return rows;
|
|
}
|
|
|
|
private Map<String, String> createRow(String id, String title, String description) {
|
|
Map<String, String> row = new HashMap<>();
|
|
row.put("id", id);
|
|
row.put("title", title);
|
|
row.put("description", description);
|
|
return row;
|
|
}
|
|
}
|