inactivity time configured

This commit is contained in:
Dev102030-pixel
2026-08-17 14:16:42 +05:30
parent 20805c1338
commit cdc98bb1d0
5 changed files with 72 additions and 2 deletions

View File

@@ -2,8 +2,10 @@ package com.example.whatsappautomation;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@EnableScheduling
public class WhatsAppAutomationApplication { public class WhatsAppAutomationApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@@ -11,6 +11,7 @@ public class UserState {
@Id @Id
private String phoneNumber; private String phoneNumber;
private String phoneNumberId;
private String patientId; private String patientId;
private String state; private String state;
private String category; private String category;
@@ -22,6 +23,7 @@ public class UserState {
private String bookingTime; private String bookingTime;
private String languagePreference = "en"; private String languagePreference = "en";
private int menuPage = 0; private int menuPage = 0;
private Long lastActiveTime = System.currentTimeMillis();
public UserState() {} public UserState() {}
@@ -41,6 +43,19 @@ public class UserState {
this.bookingDate = null; this.bookingDate = null;
this.bookingTime = null; this.bookingTime = null;
this.menuPage = 0; this.menuPage = 0;
this.lastActiveTime = System.currentTimeMillis();
}
public void expire() {
this.state = "EXPIRED";
this.category = null;
this.subCategory = null;
this.selectedItem = null;
this.price = null;
this.address = null;
this.bookingDate = null;
this.bookingTime = null;
this.menuPage = 0;
} }
public String getPhoneNumber() { public String getPhoneNumber() {
@@ -141,4 +156,20 @@ public class UserState {
public void setMenuPage(int menuPage) { public void setMenuPage(int menuPage) {
this.menuPage = menuPage; this.menuPage = menuPage;
} }
public Long getLastActiveTime() {
return lastActiveTime;
}
public void setLastActiveTime(Long lastActiveTime) {
this.lastActiveTime = lastActiveTime;
}
public String getPhoneNumberId() {
return phoneNumberId;
}
public void setPhoneNumberId(String phoneNumberId) {
this.phoneNumberId = phoneNumberId;
}
} }

View File

@@ -4,6 +4,9 @@ import com.example.whatsappautomation.entity.UserState;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List;
@Repository @Repository
public interface UserStateRepository extends JpaRepository<UserState, String> { public interface UserStateRepository extends JpaRepository<UserState, String> {
List<UserState> findByStateNotAndLastActiveTimeBefore(String state, Long cutoffTime);
} }

View File

@@ -35,6 +35,9 @@ public class ChatbotService {
@Value("${whatsapp.access-token}") @Value("${whatsapp.access-token}")
private String accessToken; private String accessToken;
@Value("${conversation.inactivity.timeout:120}")
private long inactivityTimeoutSeconds;
private final RestTemplate restTemplate = new RestTemplate(); private final RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper(); private final ObjectMapper objectMapper = new ObjectMapper();
@@ -55,13 +58,21 @@ public class ChatbotService {
currentFrom.set(from); currentFrom.set(from);
try { try {
UserState userState = userStateRepository.findById(from).orElse(new UserState(from)); UserState userState = userStateRepository.findById(from).orElse(new UserState(from));
userState.setPhoneNumberId(phoneNumberId);
String lowerInput = messageText.trim().toLowerCase();
// Global Reset: Handling basic greetings // Global Reset: Handling basic greetings
String lowerInput = messageText.trim().toLowerCase();
if (lowerInput.equals("hi") || lowerInput.equals("hello") || lowerInput.equals("hey") || lowerInput.equals("0")) { if (lowerInput.equals("hi") || lowerInput.equals("hello") || lowerInput.equals("hey") || lowerInput.equals("0")) {
userState.reset(); userState.reset();
} else if ("EXPIRED".equals(userState.getState())) {
// If expired and not a greeting, ignore or return without processing
return;
} }
// Refresh activity timer
userState.setLastActiveTime(System.currentTimeMillis());
String response = handleState(userState, messageText.trim()); String response = handleState(userState, messageText.trim());
// If not in MAIN_MENU or LANGUAGE_SELECTION, append restart hint // If not in MAIN_MENU or LANGUAGE_SELECTION, append restart hint
@@ -1178,4 +1189,24 @@ public class ChatbotService {
sendInteractiveList(bodyText, buttonText, sectionTitle, ids, titles); sendInteractiveList(bodyText, buttonText, sectionTitle, ids, titles);
} }
} }
@org.springframework.scheduling.annotation.Scheduled(fixedDelay = 30000) // Runs every 30 seconds
public void pollInactiveSessions() {
long cutoffTime = System.currentTimeMillis() - (inactivityTimeoutSeconds * 1000);
List<UserState> inactiveUsers = userStateRepository.findByStateNotAndLastActiveTimeBefore("EXPIRED", cutoffTime);
for (UserState user : inactiveUsers) {
user.expire();
userStateRepository.save(user);
// Send fallback message
String fallbackText = "en".equals(user.getLanguagePreference())
? "It looks like your previous conversation has ended.\n👋 To start a new conversation, please type Hi or Hello."
: "உங்கள் முந்தைய உரையாடல் முடிவடைந்துவிட்டது.\n👋 புதிய உரையாடலைத் தொடங்க Hi அல்லது Hello என டைப் செய்யவும்.";
if (user.getPhoneNumberId() != null) {
sendMessage(user.getPhoneNumberId(), user.getPhoneNumber(), fallbackText);
}
}
}
} }

View File

@@ -1,7 +1,7 @@
spring.application.name=whatsapp-automation spring.application.name=whatsapp-automation
server.port=8085 server.port=8085
whatsapp.access-token=EAAOZCONMSXCkBSHaYF1PqnnZAVjcmLqoOOJZCcbQGVWfWxILu9n0hQZBnUVGJG8WZBnLiZASM7etogv1xGj2PZCCmQPhFYyAKrhagFeYoi9fUZCfTryKonhStH3OU3RnHuZCxIWhnVIkIKe4byuOwqOv47SmM815ZCHUZA33fEhxPe9Onr1lg4tOnDeJMHoRYyDtcpWPbpc1eDbZBcy3vXwLslaBwx94xovhSKPpkDNgttTWsNBMnhbT7rKmnXEZAqDwWSg5FhITKePQS9HQ5troiyrXb whatsapp.access-token=EAAOZCONMSXCkBSL3CC4fKfY9X4ZAV8VzgQbiVx3qc05mdTSPgyy32jxSVVRDA5bGN3tcNmBmU5fWrqeRYYZCZApsobi4lZCWBrWBXJjEDQrxdTvZCdDZCjv7GZBgidEqZBboKbi5ZA9Yi864jE8mYmZAtjitliIKJ1nDsHpJpY0tZB2kpaZAKnnfHf9RcZBixr8owGaGHUvok4LO1SVNNZBJ4ZAr7JrZC5DY3vi402sGPOnY9n8QXGzIRKrcmFij74xAWKhybZAgvHIZBAIVsuicybPiDfVy8ZBN
whatsapp.verify-token=my_whatsapp_verify_token_123 whatsapp.verify-token=my_whatsapp_verify_token_123
spring.datasource.url=jdbc:postgresql://localhost:5432/rmc_bot spring.datasource.url=jdbc:postgresql://localhost:5432/rmc_bot
@@ -15,3 +15,6 @@ spring.jpa.show-sql=true
spring.messages.encoding=UTF-8 spring.messages.encoding=UTF-8
# Conversation timeout in seconds
conversation.inactivity.timeout=120