Time table feature initiated

This commit is contained in:
Sidharth Prabhu
2026-08-20 09:54:51 +05:30
parent 32b16f363d
commit f0011b4af1
3 changed files with 118 additions and 1 deletions

View File

@@ -186,6 +186,11 @@ public class WebhookController {
return; return;
} }
if ("student_weekly_timetable".equals(selectedButtonId)) {
studentMenuHandler.handleWeeklyTimetable(phoneNumber);
return;
}
if (currentState == UserState.AWAITING_GRIEVANCE_CATEGORY) { if (currentState == UserState.AWAITING_GRIEVANCE_CATEGORY) {
grievanceHandler.handleCategorySelection(phoneNumber, selectedButtonId); grievanceHandler.handleCategorySelection(phoneNumber, selectedButtonId);
} else { } else {

View File

@@ -69,7 +69,21 @@ public class StudentMenuHandler {
case "student_timetable": case "student_timetable":
String rawTimetable = imsApiService.getTimetable(token); String rawTimetable = imsApiService.getTimetable(token);
sendResponseWithMenu(phoneNumber, MessageFormatter.formatTimetable(rawTimetable)); 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, Object> buttonMessage = WhatsAppMessageBuilder.buildButtonMessage(todaySchedule, buttons);
messageService.sendInteractiveMessage(phoneNumber, buttonMessage);
break; break;
case "student_internal_marks": case "student_internal_marks":
@@ -217,6 +231,23 @@ public class StudentMenuHandler {
sessionService.resetState(phoneNumber); // Reset state after fetching receipt 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 Student Menu list message
sendResponseWithMenu(phoneNumber, "Select an option from the menu below.");
}
private void sendResponseWithMenu(String phoneNumber, String bodyText) { private void sendResponseWithMenu(String phoneNumber, String bodyText) {
// Meta API interactive list body limit is 1024 characters // Meta API interactive list body limit is 1024 characters
if (bodyText.length() > 1024) { if (bodyText.length() > 1024) {

View File

@@ -443,4 +443,85 @@ public class MessageFormatter {
} catch (Exception e) {} } catch (Exception e) {}
return rows; return rows;
} }
public static String formatWeeklyTimetable(String rawJson) {
if (rawJson == null) return "❌ Failed to retrieve weekly timetable data.";
try {
JsonNode root = mapper.readTree(rawJson);
if (!root.has("data") || !root.get("data").isObject() || !root.get("data").has("schedule")) {
return "❌ Weekly timetable details not available in the response.";
}
JsonNode schedule = root.get("data").get("schedule");
StringBuilder sb = new StringBuilder();
sb.append("📅 *Weekly Class Timetable*\n\n");
sb.append("```\n");
sb.append(String.format("%-3s | %-11s | %s\n", "Day", "Time/Period", "Subject (Room)"));
sb.append("----+-------------+------------------------\n");
String[] days = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"};
String[] dayAbbrevs = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
boolean hasAnyClasses = false;
for (int i = 0; i < days.length; i++) {
String day = days[i];
String abbrev = dayAbbrevs[i];
if (schedule.has(day)) {
JsonNode daySchedule = schedule.get(day);
if (daySchedule.isObject() && daySchedule.size() > 0) {
java.util.Iterator<java.util.Map.Entry<String, JsonNode>> fields = daySchedule.fields();
while (fields.hasNext()) {
java.util.Map.Entry<String, JsonNode> field = fields.next();
String timeOrPeriod = field.getKey();
JsonNode details = field.getValue();
String course = "";
String room = "";
if (details.isObject()) {
course = details.has("course_name") ? details.get("course_name").asText() :
(details.has("name") ? details.get("name").asText() : "Unknown");
room = details.has("room") ? details.get("room").asText() : "";
} else {
course = details.asText();
}
String subjectRoom = room.isEmpty() ? course : course + " (" + room + ")";
sb.append(String.format("%-3s | %-11s | %s\n", abbrev, truncate(timeOrPeriod, 11), subjectRoom));
hasAnyClasses = true;
}
} else if (daySchedule.isArray() && daySchedule.size() > 0) {
for (JsonNode details : daySchedule) {
String time = details.has("time") ? details.get("time").asText() : "TBA";
String course = details.has("course_name") ? details.get("course_name").asText() : "Unknown";
String room = details.has("room") ? details.get("room").asText() : "";
String subjectRoom = room.isEmpty() ? course : course + " (" + room + ")";
sb.append(String.format("%-3s | %-11s | %s\n", abbrev, truncate(time, 11), subjectRoom));
hasAnyClasses = true;
}
}
}
}
sb.append("```");
if (!hasAnyClasses) {
return "📅 *Weekly Class Timetable*\n\nNo classes scheduled for this week.";
}
return sb.toString();
} catch (Exception e) {
return "⚠️ Error formatting weekly timetable data.";
}
}
private static String truncate(String text, int length) {
if (text == null) return "";
if (text.length() <= length) return text;
return text.substring(0, length);
}
} }