Time Table Fixed

This commit is contained in:
RIT Services
2026-08-20 04:58:20 +00:00
parent f0011b4af1
commit 9d83dec681
6 changed files with 557 additions and 87 deletions

Binary file not shown.

View File

@@ -943,3 +943,339 @@ org.h2.jdbc.JdbcSQLNonTransientConnectionException: Database is already closed (
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:480)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:57)
at java.base/java.lang.Thread.run(Thread.java:1447)
2026-08-20 04:52:46.342121Z database: flush
org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /opt/projects/RITz-whatsapp-bot/db/whatsappbot.mv.db [2.4.240/7]" [50000-240]
at org.h2.message.DbException.get(DbException.java:212)
at org.h2.message.DbException.convert(DbException.java:407)
at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
at org.h2.mvstore.MVStore.handleException(MVStore.java:1675)
at org.h2.mvstore.MVStore.panic(MVStore.java:502)
at org.h2.mvstore.MVStore.<init>(MVStore.java:296)
at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2164)
at org.h2.mvstore.db.Store.<init>(Store.java:133)
at org.h2.engine.Database.<init>(Database.java:328)
at org.h2.engine.Engine.openSession(Engine.java:92)
at org.h2.engine.Engine.openSession(Engine.java:222)
at org.h2.engine.Engine.createSession(Engine.java:201)
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:350)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:124)
at org.h2.Driver.connect(Driver.java:59)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:144)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:373)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:210)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:488)
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:576)
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:97)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
at org.hibernate.engine.jdbc.connections.internal.DataSourceConnectionProvider.getConnection(DataSourceConnectionProvider.java:149)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:508)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:48)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:366)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironment(JdbcEnvironmentInitiator.java:143)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:120)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:80)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:133)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:260)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:235)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:212)
at org.hibernate.boot.model.relational.Database.<init>(Database.java:44)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:251)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:203)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:180)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1388)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.populateSessionFactoryBuilder(EntityManagerFactoryBuilderImpl.java:1468)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1450)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:93)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:443)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:436)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:411)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:419)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1862)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1811)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:977)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:621)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:756)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:445)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$2(SpringBootContextLoader.java:155)
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1465)
at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:600)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:155)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:114)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:247)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.lambda$loadContext$0(DefaultCacheAwareContextLoaderDelegate.java:167)
at org.springframework.test.context.cache.DefaultContextCache.put(DefaultContextCache.java:214)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:160)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:128)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:200)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:139)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:242)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$1(ClassBasedTestDescriptor.java:423)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:428)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$0(ClassBasedTestDescriptor.java:422)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:422)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$0(ClassBasedTestDescriptor.java:334)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:333)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$1(ClassBasedTestDescriptor.java:322)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$0(ClassBasedTestDescriptor.java:321)
at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:27)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:126)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:70)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$0(NodeTestTask.java:144)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:144)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:110)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:42)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$2(NodeTestTask.java:180)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$1(NodeTestTask.java:166)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$0(NodeTestTask.java:164)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:163)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:116)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:42)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$2(NodeTestTask.java:180)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$1(NodeTestTask.java:166)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$0(NodeTestTask.java:164)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:163)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:116)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:36)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:52)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:58)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.executeEngine(EngineExecutionOrchestrator.java:246)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.failOrExecuteEngine(EngineExecutionOrchestrator.java:218)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:179)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:66)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:157)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:65)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:125)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:58)
at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$2(InterceptingLauncher.java:57)
at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25)
at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:56)
at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:58)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:125)
at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithCancellationToken(LauncherAdapter.java:68)
at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:54)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /opt/projects/RITz-whatsapp-bot/db/whatsappbot.mv.db [2.4.240/7]" [50000-240]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
... 153 more
Caused by: org.h2.mvstore.MVStoreException: The file is locked: /opt/projects/RITz-whatsapp-bot/db/whatsappbot.mv.db [2.4.240/7]
at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
at org.h2.mvstore.MVStore.<init>(MVStore.java:291)
... 147 more
2026-08-20 04:52:47.925225Z database: flush
org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /opt/projects/RITz-whatsapp-bot/db/whatsappbot.mv.db [2.4.240/7]" [50000-240]
at org.h2.message.DbException.get(DbException.java:212)
at org.h2.message.DbException.convert(DbException.java:407)
at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
at org.h2.mvstore.MVStore.handleException(MVStore.java:1675)
at org.h2.mvstore.MVStore.panic(MVStore.java:502)
at org.h2.mvstore.MVStore.<init>(MVStore.java:296)
at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2164)
at org.h2.mvstore.db.Store.<init>(Store.java:133)
at org.h2.engine.Database.<init>(Database.java:328)
at org.h2.engine.Engine.openSession(Engine.java:92)
at org.h2.engine.Engine.openSession(Engine.java:222)
at org.h2.engine.Engine.createSession(Engine.java:201)
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:350)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:124)
at org.h2.Driver.connect(Driver.java:59)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:144)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:373)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:210)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:488)
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:576)
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:97)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111)
at org.hibernate.engine.jdbc.connections.internal.DataSourceConnectionProvider.getConnection(DataSourceConnectionProvider.java:149)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:508)
at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:44)
at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:37)
at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:61)
at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:41)
at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:36)
at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:73)
at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:63)
at org.hibernate.tool.schema.extract.internal.CachingDatabaseInformationImpl.<init>(CachingDatabaseInformationImpl.java:43)
at org.hibernate.tool.schema.internal.GroupedSchemaMigratorImpl.buildDatabaseInformation(GroupedSchemaMigratorImpl.java:112)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:83)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:269)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$1(SchemaManagementToolCoordinator.java:101)
at java.base/java.util.HashMap.forEach(HashMap.java:1429)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:100)
at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:35)
at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:33)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:327)
at org.hibernate.internal.SessionFactoryRegistry.instantiateSessionFactory(SessionFactoryRegistry.java:64)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:458)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1452)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:93)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:443)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:436)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:411)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:419)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1862)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1811)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:371)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:331)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:201)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:977)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:621)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:756)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:445)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$2(SpringBootContextLoader.java:155)
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1465)
at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:600)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:155)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:114)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:247)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.lambda$loadContext$0(DefaultCacheAwareContextLoaderDelegate.java:167)
at org.springframework.test.context.cache.DefaultContextCache.put(DefaultContextCache.java:214)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:160)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:128)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:200)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:139)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:260)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:242)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$1(ClassBasedTestDescriptor.java:423)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:428)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$0(ClassBasedTestDescriptor.java:422)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:422)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$0(ClassBasedTestDescriptor.java:334)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:333)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$1(ClassBasedTestDescriptor.java:322)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$0(ClassBasedTestDescriptor.java:321)
at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:27)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:126)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:70)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$0(NodeTestTask.java:144)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:144)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:110)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:42)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$2(NodeTestTask.java:180)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$1(NodeTestTask.java:166)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$0(NodeTestTask.java:164)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:163)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:116)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:42)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$2(NodeTestTask.java:180)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$1(NodeTestTask.java:166)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$0(NodeTestTask.java:164)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:74)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:163)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:116)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:36)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:52)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:58)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.executeEngine(EngineExecutionOrchestrator.java:246)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.failOrExecuteEngine(EngineExecutionOrchestrator.java:218)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:179)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:66)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:157)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:65)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:125)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:58)
at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$2(InterceptingLauncher.java:57)
at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25)
at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:56)
at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:58)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:125)
at org.apache.maven.surefire.junitplatform.LauncherAdapter.executeWithCancellationToken(LauncherAdapter.java:68)
at org.apache.maven.surefire.junitplatform.LauncherAdapter.execute(LauncherAdapter.java:54)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:203)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:168)
at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:136)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: /opt/projects/RITz-whatsapp-bot/db/whatsappbot.mv.db [2.4.240/7]" [50000-240]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
... 157 more
Caused by: org.h2.mvstore.MVStoreException: The file is locked: /opt/projects/RITz-whatsapp-bot/db/whatsappbot.mv.db [2.4.240/7]
at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
at org.h2.mvstore.MVStore.<init>(MVStore.java:291)
... 151 more

View File

@@ -81,6 +81,7 @@ public class StudentMenuHandler {
weeklyBtn.put("id", "student_weekly_timetable");
weeklyBtn.put("title", "Weekly Timetable");
buttons.add(weeklyBtn);
System.out.println("FINAL TODAY TIMETABLE MESSAGE:\n" + todaySchedule);
Map<String, Object> buttonMessage = WhatsAppMessageBuilder.buildButtonMessage(todaySchedule, buttons);
messageService.sendInteractiveMessage(phoneNumber, buttonMessage);

View File

@@ -95,74 +95,136 @@ public class MessageFormatter {
return sb.toString();
}
public static String formatTimetable(String rawJson) {
private static class TimetableEntry {
String subjectName;
String subjectCode;
String staffName;
String staffCode;
public TimetableEntry(String subjectName, String subjectCode, String staffName, String staffCode) {
this.subjectName = subjectName != null ? subjectName.trim() : "";
this.subjectCode = subjectCode != null ? subjectCode.trim() : "";
this.staffName = staffName != null ? staffName.trim() : "";
this.staffCode = staffCode != null ? staffCode.trim() : "";
}
public boolean isValid() {
return !subjectName.isEmpty() && !subjectCode.isEmpty();
}
public String getUniqueKey() {
return subjectName + "||" + subjectCode;
}
}
public static String formatTodayTimetable(String rawJson) {
String day = java.time.LocalDate.now()
.getDayOfWeek()
.getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.ENGLISH)
.toLowerCase(java.util.Locale.ROOT);
return formatTodayTimetableForDay(rawJson, day);
}
public static String formatTodayTimetableForDay(String rawJson, String day) {
if (rawJson == null) return "❌ Failed to retrieve timetable data.";
try {
JsonNode root = mapper.readTree(rawJson);
if (!root.has("data") || !root.get("data").isObject() || !root.get("data").has("schedule")) {
return "❌ Timetable details not available in this format.";
}
JsonNode schedule = root.get("data").get("schedule");
System.out.println("TIMETABLE DEBUG");
System.out.println("Current day: " + day.toUpperCase());
System.out.println("Normalized day: " + day);
boolean hasSchedule = schedule.has(day);
System.out.println("Schedule found: " + hasSchedule);
StringBuilder sb = new StringBuilder();
sb.append("\ud83d\uddd3\ufe0f *Today's Classes*\n\n");
sb.append("📅 *Today's Classes*\n");
sb.append("━━━━━━━━━━━━━━\n\n");
boolean validFormat = false;
boolean hasClassesToday = false;
if (root.has("data") && root.get("data").isObject() && root.get("data").has("schedule")) {
validFormat = true;
JsonNode schedule = root.get("data").get("schedule");
if (hasSchedule) {
JsonNode daySchedule = schedule.get(day);
String today = java.time.LocalDate.now().getDayOfWeek().toString().toLowerCase();
int maxPeriod = 7;
java.util.Iterator<String> fieldNames = daySchedule.fieldNames();
java.util.List<String> foundPeriods = new java.util.ArrayList<>();
while (fieldNames.hasNext()) {
String fName = fieldNames.next();
foundPeriods.add(fName);
try {
int p = Integer.parseInt(fName);
if (p > maxPeriod) {
maxPeriod = p;
}
} catch (NumberFormatException e) {}
}
System.out.println("Periods found: [" + String.join(", ", foundPeriods) + "]");
if (schedule.has(today)) {
JsonNode todaySchedule = schedule.get(today);
for (int period = 1; period <= maxPeriod; period++) {
String periodKey = String.valueOf(period);
sb.append(getNumberEmoji(period)).append(" ");
if (todaySchedule.isObject() && todaySchedule.size() > 0) {
java.util.Iterator<java.util.Map.Entry<String, JsonNode>> fields = todaySchedule.fields();
while (fields.hasNext()) {
java.util.Map.Entry<String, JsonNode> field = fields.next();
String timeOrPeriod = field.getKey();
JsonNode details = field.getValue();
if (details.isObject()) {
String course = details.has("course_name") ? details.get("course_name").asText() :
(details.has("name") ? details.get("name").asText() : "Unknown");
String room = details.has("room") ? details.get("room").asText() : "";
sb.append("*").append(timeOrPeriod).append(":* ").append(course);
if (!room.isEmpty()) sb.append(" (Room ").append(room).append(")");
sb.append("\n");
} else {
sb.append("*").append(timeOrPeriod).append(":* ").append(details.asText()).append("\n");
if (daySchedule.has(periodKey)) {
JsonNode periodNode = daySchedule.get(periodKey);
java.util.List<TimetableEntry> entries = new java.util.ArrayList<>();
if (periodNode.isArray()) {
for (JsonNode node : periodNode) {
String sName = node.has("subjectName") ? node.get("subjectName").asText() : "";
String sCode = node.has("subjectCode") ? node.get("subjectCode").asText() : "";
String stName = node.has("staffName") ? node.get("staffName").asText() : "";
String stCode = node.has("staffCode") ? node.get("staffCode").asText() : "";
entries.add(new TimetableEntry(sName, sCode, stName, stCode));
}
hasClassesToday = true;
}
} else if (todaySchedule.isArray() && todaySchedule.size() > 0) {
for (JsonNode details : todaySchedule) {
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() : "";
sb.append("*").append(time).append(":* ").append(course);
if (!room.isEmpty()) sb.append(" (Room ").append(room).append(")");
sb.append("\n");
hasClassesToday = true;
System.out.println("Period " + period + " entries: " + entries.size());
if (!entries.isEmpty()) {
TimetableEntry first = entries.get(0);
System.out.println("Period " + period + " first subjectName: " + first.subjectName);
System.out.println("Period " + period + " first subjectCode: " + first.subjectCode);
}
java.util.Map<String, TimetableEntry> uniqueMap = new java.util.LinkedHashMap<>();
for (TimetableEntry entry : entries) {
if (entry.isValid()) {
uniqueMap.putIfAbsent(entry.getUniqueKey(), entry);
}
}
if (!uniqueMap.isEmpty()) {
java.util.List<String> formattedSubjects = new java.util.ArrayList<>();
for (TimetableEntry entry : uniqueMap.values()) {
formattedSubjects.add("*" + entry.subjectName + "*\n `" + entry.subjectCode + "`");
}
sb.append(String.join(" / ", formattedSubjects)).append("\n\n");
} else {
sb.append("*Free Period*\n\n");
}
} else {
sb.append("*Free Period*\n\n");
}
}
} else {
sb.append("No classes scheduled for today.\n\n");
}
if (validFormat && !hasClassesToday) {
sb.append("No classes scheduled for today.\n");
} else if (!validFormat) {
sb.append("Details not available in this format.\n");
sb.append("\n\n*DEBUG RAW JSON:*\n").append(rawJson);
}
sb.append("━━━━━━━━━━━━━━");
return sb.toString();
} catch (Exception e) {
return "⚠️ Error formatting timetable data.\nRAW JSON: " + rawJson;
System.err.println("Error formatting today's timetable: " + e.getMessage());
return "⚠️ Error formatting timetable data.";
}
}
public static String formatTimetable(String rawJson) {
return formatTodayTimetable(rawJson);
}
public static String formatResults(String rawJson, int semester) {
if (rawJson == null) return "❌ Failed to retrieve semester results.";
@@ -444,76 +506,105 @@ public class MessageFormatter {
return rows;
}
private static String getNumberEmoji(int num) {
switch (num) {
case 1: return "1️⃣";
case 2: return "2️⃣";
case 3: return "3️⃣";
case 4: return "4️⃣";
case 5: return "5️⃣";
case 6: return "6️⃣";
case 7: return "7️⃣";
case 8: return "8️⃣";
case 9: return "9️⃣";
default: return num + "️⃣";
}
}
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");
sb.append("📚 WEEKLY TIMETABLE\n\n");
String[] days = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"};
String[] dayAbbrevs = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
String[] days = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
String[] dayLabels = {"MON", "TUE", "WED", "THU", "FRI", "SAT"};
boolean hasAnyClasses = false;
for (int i = 0; i < days.length; i++) {
String day = days[i];
String abbrev = dayAbbrevs[i];
String label = dayLabels[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();
sb.append(label).append("\n");
int maxPeriod = 7;
java.util.Iterator<String> fieldNames = daySchedule.fieldNames();
while (fieldNames.hasNext()) {
try {
int p = Integer.parseInt(fieldNames.next());
if (p > maxPeriod) {
maxPeriod = p;
}
} catch (NumberFormatException e) {}
}
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);
java.util.Set<String> subjects = new java.util.LinkedHashSet<>();
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();
if (details.isArray()) {
for (JsonNode entry : details) {
String name = entry.has("subjectName") ? entry.get("subjectName").asText() : "";
String code = entry.has("subjectCode") ? entry.get("subjectCode").asText() : "";
if (!name.trim().isEmpty()) {
subjects.add(name.trim() + " — " + code.trim());
}
}
} else if (details.isObject()) {
String name = details.has("course_name") ? details.get("course_name").asText() :
(details.has("name") ? details.get("name").asText() :
(details.has("subjectName") ? details.get("subjectName").asText() : ""));
String code = details.has("course_code") ? details.get("course_code").asText() :
(details.has("code") ? details.get("code").asText() :
(details.has("subjectCode") ? details.get("subjectCode").asText() : ""));
if (!name.trim().isEmpty()) {
subjects.add(name.trim() + " — " + code.trim());
}
}
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;
if (!subjects.isEmpty()) {
sb.append(String.join(" / ", subjects)).append("\n");
hasAnyClasses = true;
} else {
sb.append("—\n");
}
} else {
sb.append("—\n");
}
}
sb.append("\n");
}
}
sb.append("```");
if (!hasAnyClasses) {
return "📅 *Weekly Class Timetable*\n\nNo classes scheduled for this week.";
return "📚 WEEKLY TIMETABLE\n\nNo classes scheduled for this week.";
}
return sb.toString();
return sb.toString().trim();
} catch (Exception e) {
return "⚠️ Error formatting weekly timetable data.";
}

View File

@@ -19,4 +19,4 @@ spring.h2.console.enabled=true
# Encryption Secret for Passcodes (Must be 16, 24, or 32 bytes)
bot.encryption.secret=12345678901234567890123456789012
whatsapp.api-token=EAAc3Wjql00oBSdoBhXozC8gKyWN9Il6cqpjvE531hZAnuFqOfHCuCBGt8hYZCICzm2dnXsH2RR3HIi3dpZAZBbNFE9Xj8Hvs3TS94nHrmxevicgThlqSQDjZCDm6SS1qFvt7NwRjiy1TWtZCuLLvcTxyjjNPUtjt91OZBr5DtddHzESLezP6R3oJEzIhSjLqlRAvNwfhW8wDYiCkkx0Qw69iO2UeodHw5E8Q86kZCPEvocldDZCyb7qZCMZAELPbYJYkWVLk8MjVyZAXjmnoGFnS5n4ZAsXBE
whatsapp.api-token=EAAc3Wjql00oBSUjYhQ1TZBiNJNmwNlpktCtJpqSLXycDVjWjPiP5dBWHvvFX2Deq1tGXQO2jgVOGChnJk9jsMxLVdxvUs4z7g7xlfcQtAPYiHwvQbPVSbGTTCBvjv2IvHf7Ql2iNBKL72GZCrxAJrQpmjHUG5sbQkVWmMpNfwgI52iDBw0BifU1QhQHFEOnQfiPu19KUp3hJOg6XkUbbXyfBKvbSkZB57xj0XHMv6wgpqDrQwAACOjSlSPrNEC3eZB9DbZAqWYnPkJCsX99Pz3GhA

View File

@@ -10,4 +10,46 @@ class WhatsappBotApplicationTests {
void contextLoads() {
}
@Test
void testFormatTodayTimetableThursday() {
String thursdayJson = "{\n" +
" \"success\": true,\n" +
" \"data\": {\n" +
" \"schedule\": {\n" +
" \"thursday\": {\n" +
" \"1\": [{\"subjectName\":\"Business Analytics\",\"subjectCode\":\"CB23531\",\"staffName\":\"FOUZIA SULTHANA K.\",\"staffCode\":\"CS84\"}],\n" +
" \"2\": [{\"subjectName\":\"Computer Networks\",\"subjectCode\":\"CS23511\",\"staffName\":\"SELVAKUMARAN S.\",\"staffCode\":\"CS91\"}],\n" +
" \"3\": [\n" +
" {\"subjectName\":\"Deep Learning\",\"subjectCode\":\"AD23511\",\"staffName\":\"DIVYA S\",\"staffCode\":\"CS193\"},\n" +
" {\"subjectName\":\"Deep Learning\",\"subjectCode\":\"AD23511\",\"staffName\":\"SARANYA S.\",\"staffCode\":\"CS85\"},\n" +
" {\"subjectName\":\"Deep Learning\",\"subjectCode\":\"AD23511\",\"staffName\":\"DR.VIDHYA M\",\"staffCode\":\"CS256\"},\n" +
" {\"subjectName\":\"Deep Learning\",\"subjectCode\":\"AD23511\",\"staffName\":\"SANDHIYARAJESHWARI K\",\"staffCode\":\"CS153\"},\n" +
" {\"subjectName\":\"Deep Learning\",\"subjectCode\":\"AD23511\",\"staffName\":\"MONIKAA R\",\"staffCode\":\"CS178\"},\n" +
" {\"subjectName\":\"Deep Learning\",\"subjectCode\":\"AD23511\",\"staffName\":\"ARTHI A.\",\"staffCode\":\"CS87\"}\n" +
" ],\n" +
" \"4\": [{\"subjectName\":\"Image and Video Analytics\",\"subjectCode\":\"AD23V15\",\"staffName\":\"JOEL J\",\"staffCode\":\"CS226\"}],\n" +
" \"5\": [{\"subjectName\":\"Big Data Analytics\",\"subjectCode\":\"AD23V12\",\"staffName\":\"KAVITHA V\",\"staffCode\":\"CS253\"}],\n" +
" \"6\": [\n" +
" {\"subjectName\":\"Data Exploration and Visualization\",\"subjectCode\":\"AD23532\",\"staffName\":\"DR.VIDHYA M\",\"staffCode\":\"CS256\"},\n" +
" {\"subjectName\":\"Data Exploration and Visualization\",\"subjectCode\":\"AD23532\",\"staffName\":\"DR.VIDHYA M\",\"staffCode\":\"CS256\"}\n" +
" ],\n" +
" \"7\": [{\"subjectName\":\"\",\"subjectCode\":\"\",\"staffName\":\"FOUZIA SULTHANA K.\",\"staffCode\":\"CS84\"}]\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
String formatted = com.rit.whatsapp.util.MessageFormatter.formatTodayTimetableForDay(thursdayJson, "thursday");
System.out.println("Formatted output:\n" + formatted);
org.junit.jupiter.api.Assertions.assertTrue(formatted.contains("📅 *Today's Classes*"));
org.junit.jupiter.api.Assertions.assertTrue(formatted.contains("1️⃣ *Business Analytics*\n `CB23531`"));
org.junit.jupiter.api.Assertions.assertTrue(formatted.contains("2️⃣ *Computer Networks*\n `CS23511`"));
org.junit.jupiter.api.Assertions.assertTrue(formatted.contains("3️⃣ *Deep Learning*\n `AD23511`"));
org.junit.jupiter.api.Assertions.assertTrue(formatted.contains("4️⃣ *Image and Video Analytics*\n `AD23V15`"));
org.junit.jupiter.api.Assertions.assertTrue(formatted.contains("5️⃣ *Big Data Analytics*\n `AD23V12`"));
org.junit.jupiter.api.Assertions.assertTrue(formatted.contains("6️⃣ *Data Exploration and Visualization*\n `AD23532`"));
org.junit.jupiter.api.Assertions.assertTrue(formatted.contains("7️⃣ *Free Period*"));
}
}