├── .github └── workflows │ └── main_pwr-api-dev.yml ├── .gitignore ├── .idea └── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── dev │ │ └── wms │ │ └── pwrapi │ │ ├── PwrApiApplication.java │ │ ├── api │ │ ├── EdukacjaAPI.java │ │ ├── EportalAPI.java │ │ ├── ForumAPI.java │ │ ├── JsosAPI.java │ │ ├── NewsAPI.java │ │ ├── ParkingAPI.java │ │ └── ProwadzacyAPI.java │ │ ├── dao │ │ ├── edukacja │ │ │ ├── EduMessageDAOImpl.java │ │ │ ├── EduSubjectDAO.java │ │ │ └── EduSubjectDAOImpl.java │ │ ├── eportal │ │ │ ├── EportalCalendarDAO.java │ │ │ └── EportalDAO.java │ │ ├── forum │ │ │ ├── ForumDAO.java │ │ │ └── ForumDAOImpl.java │ │ ├── jsos │ │ │ ├── JsosDataDAO.java │ │ │ ├── JsosDataDAOImpl.java │ │ │ ├── JsosGeneralDAO.java │ │ │ ├── JsosGeneralDAOImpl.java │ │ │ ├── JsosLessonsDAO.java │ │ │ └── JsosLessonsDAOImpl.java │ │ ├── news │ │ │ └── NewsDAO.java │ │ ├── parking │ │ │ ├── IParkingDAO.java │ │ │ ├── ParkingDAO.java │ │ │ └── SKDParkingDAO.java │ │ └── prowadzacy │ │ │ ├── ProwadzacyDAO.java │ │ │ └── ProwadzacyDAOImpl.java │ │ ├── dto │ │ ├── ExceptionMessagingDTO.java │ │ ├── edukacja │ │ │ └── EduConnection.java │ │ ├── eportal │ │ │ ├── courseTitle.java │ │ │ ├── deserialization │ │ │ │ ├── Course.java │ │ │ │ ├── Data.java │ │ │ │ └── Root.java │ │ │ ├── sections │ │ │ │ ├── EportalElementType.java │ │ │ │ ├── EportalSection.java │ │ │ │ └── EportalSectionElement.java │ │ │ └── userDetails.java │ │ ├── jsos │ │ │ └── JsosConnection.java │ │ ├── news │ │ │ ├── Channel.java │ │ │ ├── FacultyType.java │ │ │ ├── Item.java │ │ │ └── Rss.java │ │ └── parking │ │ │ ├── DataWithLabels.java │ │ │ ├── IParkingResponse.java │ │ │ ├── Parking.java │ │ │ ├── ParkingWithHistory.java │ │ │ └── deserialization │ │ │ ├── ParkingArrayElement.java │ │ │ ├── ParkingResponse.java │ │ │ ├── ParkingWithHistoryArrayElement.java │ │ │ ├── ParkingWithHistoryChart.java │ │ │ └── ParkingWithHistoryResponse.java │ │ ├── entity │ │ ├── edukacja │ │ │ ├── Group.java │ │ │ └── Subject.java │ │ ├── eportal │ │ │ ├── Mark.java │ │ │ ├── MarkSummary.java │ │ │ └── calendar │ │ │ │ ├── CalendarEvent.java │ │ │ │ └── CalendarMonth.java │ │ ├── forum │ │ │ ├── Review.java │ │ │ └── Teacher.java │ │ ├── jsos │ │ │ ├── JsosLesson.java │ │ │ ├── JsosStudentData.java │ │ │ ├── finance │ │ │ │ ├── FinanceEntry.java │ │ │ │ ├── FinanceResult.java │ │ │ │ └── operations │ │ │ │ │ ├── FinanceOperationResult.java │ │ │ │ │ └── OperationEntry.java │ │ │ ├── marks │ │ │ │ ├── JsosMark.java │ │ │ │ └── JsosSemester.java │ │ │ ├── messages │ │ │ │ ├── JsosMessageFull.java │ │ │ │ └── JsosMessageShort.java │ │ │ └── weeks │ │ │ │ ├── JsosDay.java │ │ │ │ ├── JsosDaySubject.java │ │ │ │ └── JsosWeek.java │ │ └── prowadzacy │ │ │ ├── ProwadzacyDay.java │ │ │ ├── ProwadzacyLesson.java │ │ │ └── ProwadzacyResult.java │ │ ├── http │ │ └── CORSFilter.java │ │ ├── scrapper │ │ ├── edukacja │ │ │ └── EduScrapperServices.java │ │ ├── eportal │ │ │ └── EportalScrapperService.java │ │ └── jsos │ │ │ └── JsosScrapperServices.java │ │ ├── service │ │ ├── edukacja │ │ │ ├── EduService.java │ │ │ └── EduServiceImpl.java │ │ ├── eportal │ │ │ ├── EportalService.java │ │ │ └── EportalServiceImpl.java │ │ ├── forum │ │ │ ├── ForumService.java │ │ │ └── ForumServiceImpl.java │ │ ├── jsos │ │ │ ├── JsosService.java │ │ │ └── JsosServiceImpl.java │ │ ├── news │ │ │ └── NewsService.java │ │ ├── parking │ │ │ ├── ParkingProxy.java │ │ │ ├── ParkingService.java │ │ │ └── ParkingServiceImpl.java │ │ └── prowadzacy │ │ │ ├── ProwadzacyService.java │ │ │ └── ProwadzacyServiceImpl.java │ │ └── utils │ │ ├── config │ │ ├── CachingConfig.java │ │ ├── DeserializationConfig.java │ │ └── RequestLoggingConfig.java │ │ ├── cookies │ │ └── CookieJarImpl.java │ │ ├── edukacja │ │ ├── advice │ │ │ └── EdukacjaAPIAdvice.java │ │ └── exceptions │ │ │ └── EnrollmentAccessDeniedException.java │ │ ├── eportal │ │ ├── EportalGeneralUtils.java │ │ ├── advice │ │ │ └── EportalAPIAdvice.java │ │ └── exceptions │ │ │ └── WrongCourseIdException.java │ │ ├── forum │ │ ├── advice │ │ │ └── ForumAPIAdvice.java │ │ ├── config │ │ │ └── SpringJdbcConfig.java │ │ ├── dto │ │ │ └── DatabaseMetadataDTO.java │ │ ├── exceptions │ │ │ ├── CategoryMembersNotFoundException.java │ │ │ ├── InvalidLimitException.java │ │ │ ├── ReviewNotFoundException.java │ │ │ ├── TeacherNotFoundByFullNameException.java │ │ │ └── TeacherNotFoundByIdException.java │ │ └── rowMappers │ │ │ ├── ReviewRowMapper.java │ │ │ ├── ReviewWithTeacherRowMapper.java │ │ │ └── TeacherRowMapper.java │ │ ├── generalExceptionHandling │ │ ├── GeneralAdvice.java │ │ └── ResponseMessageHandler.java │ │ ├── generalExceptions │ │ ├── ConstraintViolationExceptionAdvice.java │ │ ├── InvalidIdException.java │ │ ├── LoginException.java │ │ ├── SystemTimeoutException.java │ │ └── WrongOrderException.java │ │ ├── http │ │ └── HttpUtils.java │ │ ├── jsonProcessing │ │ └── ObjectMapperJSON.java │ │ ├── jsos │ │ ├── JsosHttpUtils.java │ │ ├── JsosLessonsUtils.java │ │ ├── advice │ │ │ └── JsosAPIAdvice.java │ │ ├── cookies │ │ │ └── CookieJarImpl.java │ │ └── exceptions │ │ │ ├── NoTodayClassException.java │ │ │ └── TooBigOffsetException.java │ │ ├── parking │ │ ├── ParkingDateUtils.java │ │ ├── ParkingGeneralUtils.java │ │ ├── advice │ │ │ └── ParkingAdvice.java │ │ └── exceptions │ │ │ └── WrongResponseCode.java │ │ └── prowadzacy │ │ └── exceptions │ │ ├── EmptyResultsException.java │ │ └── advices │ │ └── EmptyResultsExceptionAdvice.java └── resources │ ├── application.properties │ └── logback-spring.xml └── test ├── java └── dev │ └── wms │ └── pwrapi │ ├── PwrApiApplicationTests.java │ ├── eportal │ ├── EportalUtilsClassesTests.java │ └── WrongCredentialsEportalTests.java │ ├── forum │ └── ForumTests.java │ ├── jsos │ ├── UtilsClassesTests.java │ └── WrongCredentialsJsosTests.java │ ├── parking │ ├── ParkingDAOTest.java │ ├── ParkingProxySwitchingTest.java │ ├── ParkingProxyTest.java │ └── ParkingTests.java │ ├── prowadzacy │ └── ProwadzacyTests.java │ ├── service │ └── news │ │ ├── NewsServiceCachingTest.java │ │ └── NewsServiceTest.java │ └── testingUtils │ └── TestUtils.java └── resources └── parking └── parking-schema.json /.github/workflows/main_pwr-api-dev.yml: -------------------------------------------------------------------------------- 1 | # Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy 2 | # More GitHub Actions for Azure: https://github.com/Azure/actions 3 | 4 | name: Build and deploy JAR app to Azure Web App - pwr-api-dev 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - name: Set up Java version 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: '17' 23 | 24 | - name: Build with Maven 25 | run: mvn clean install 26 | 27 | - name: Upload artifact for deployment job 28 | uses: actions/upload-artifact@v2 29 | with: 30 | name: java-app 31 | path: '${{ github.workspace }}/target/*.jar' 32 | 33 | deploy: 34 | runs-on: ubuntu-latest 35 | needs: build 36 | environment: 37 | name: 'Production' 38 | url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} 39 | 40 | steps: 41 | - name: Download artifact from build job 42 | uses: actions/download-artifact@v2 43 | with: 44 | name: java-app 45 | 46 | - name: Deploy to Azure Web App 47 | id: deploy-to-webapp 48 | uses: azure/webapps-deploy@v2 49 | with: 50 | app-name: 'pwr-api-dev' 51 | slot-name: 'Production' 52 | publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_6697639BBBD841C7BB94818A12599899 }} 53 | package: '*.jar' 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/java,maven,eclipse,intellij,visualstudiocode 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=java,maven,eclipse,intellij,visualstudiocode 4 | 5 | ### Eclipse ### 6 | .metadata 7 | bin/ 8 | tmp/ 9 | *.tmp 10 | *.bak 11 | *.swp 12 | *~.nib 13 | local.properties 14 | .settings/ 15 | .loadpath 16 | .recommenders 17 | 18 | # External tool builders 19 | .externalToolBuilders/ 20 | 21 | # Locally stored "Eclipse launch configurations" 22 | *.launch 23 | 24 | # PyDev specific (Python IDE for Eclipse) 25 | *.pydevproject 26 | 27 | # CDT-specific (C/C++ Development Tooling) 28 | .cproject 29 | 30 | # CDT- autotools 31 | .autotools 32 | 33 | # Java annotation processor (APT) 34 | .factorypath 35 | 36 | # PDT-specific (PHP Development Tools) 37 | .buildpath 38 | 39 | # sbteclipse plugin 40 | .target 41 | 42 | # Tern plugin 43 | .tern-project 44 | 45 | # TeXlipse plugin 46 | .texlipse 47 | 48 | # STS (Spring Tool Suite) 49 | .springBeans 50 | 51 | # Code Recommenders 52 | .recommenders/ 53 | 54 | # Annotation Processing 55 | .apt_generated/ 56 | .apt_generated_test/ 57 | 58 | # Scala IDE specific (Scala & Java development for Eclipse) 59 | .cache-main 60 | .scala_dependencies 61 | .worksheet 62 | 63 | # Uncomment this line if you wish to ignore the project description file. 64 | # Typically, this file would be tracked if it contains build/dependency configurations: 65 | #.project 66 | 67 | ### Eclipse Patch ### 68 | # Spring Boot Tooling 69 | .sts4-cache/ 70 | 71 | ### Intellij ### 72 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 73 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 74 | 75 | # User-specific stuff 76 | .idea/**/workspace.xml 77 | .idea/**/tasks.xml 78 | .idea/**/usage.statistics.xml 79 | .idea/**/dictionaries 80 | .idea/**/shelf 81 | 82 | # AWS User-specific 83 | .idea/**/aws.xml 84 | 85 | # Generated files 86 | .idea/**/contentModel.xml 87 | 88 | # Sensitive or high-churn files 89 | .idea/**/dataSources/ 90 | .idea/**/dataSources.ids 91 | .idea/**/dataSources.local.xml 92 | .idea/**/sqlDataSources.xml 93 | .idea/**/dynamic.xml 94 | .idea/**/uiDesigner.xml 95 | .idea/**/dbnavigator.xml 96 | 97 | # Gradle 98 | .idea/**/gradle.xml 99 | .idea/**/libraries 100 | 101 | # Gradle and Maven with auto-import 102 | # When using Gradle or Maven with auto-import, you should exclude module files, 103 | # since they will be recreated, and may cause churn. Uncomment if using 104 | # auto-import. 105 | # .idea/artifacts 106 | # .idea/compiler.xml 107 | # .idea/jarRepositories.xml 108 | # .idea/modules.xml 109 | # .idea/*.iml 110 | # .idea/modules 111 | # *.iml 112 | # *.ipr 113 | 114 | # CMake 115 | cmake-build-*/ 116 | 117 | # Mongo Explorer plugin 118 | .idea/**/mongoSettings.xml 119 | 120 | # File-based project format 121 | *.iws 122 | 123 | # IntelliJ 124 | out/ 125 | 126 | # mpeltonen/sbt-idea plugin 127 | .idea_modules/ 128 | 129 | # JIRA plugin 130 | atlassian-ide-plugin.xml 131 | 132 | # Cursive Clojure plugin 133 | .idea/replstate.xml 134 | 135 | # SonarLint plugin 136 | .idea/sonarlint/ 137 | 138 | # Crashlytics plugin (for Android Studio and IntelliJ) 139 | com_crashlytics_export_strings.xml 140 | crashlytics.properties 141 | crashlytics-build.properties 142 | fabric.properties 143 | 144 | # Editor-based Rest Client 145 | .idea/httpRequests 146 | 147 | # Android studio 3.1+ serialized cache file 148 | .idea/caches/build_file_checksums.ser 149 | 150 | ### Intellij Patch ### 151 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 152 | 153 | # *.iml 154 | # modules.xml 155 | # .idea/misc.xml 156 | # *.ipr 157 | 158 | # Sonarlint plugin 159 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 160 | .idea/**/sonarlint/ 161 | 162 | # SonarQube Plugin 163 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 164 | .idea/**/sonarIssues.xml 165 | 166 | # Markdown Navigator plugin 167 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 168 | .idea/**/markdown-navigator.xml 169 | .idea/**/markdown-navigator-enh.xml 170 | .idea/**/markdown-navigator/ 171 | 172 | # Cache file creation bug 173 | # See https://youtrack.jetbrains.com/issue/JBR-2257 174 | .idea/$CACHE_FILE$ 175 | 176 | # CodeStream plugin 177 | # https://plugins.jetbrains.com/plugin/12206-codestream 178 | .idea/codestream.xml 179 | 180 | ### Java ### 181 | # Compiled class file 182 | *.class 183 | 184 | # Log file 185 | *.log 186 | 187 | # BlueJ files 188 | *.ctxt 189 | 190 | # Mobile Tools for Java (J2ME) 191 | .mtj.tmp/ 192 | 193 | # Package Files # 194 | *.jar 195 | *.war 196 | *.nar 197 | *.ear 198 | *.zip 199 | *.tar.gz 200 | *.rar 201 | 202 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 203 | hs_err_pid* 204 | replay_pid* 205 | 206 | ### Maven ### 207 | target/ 208 | pom.xml.tag 209 | pom.xml.releaseBackup 210 | pom.xml.versionsBackup 211 | pom.xml.next 212 | release.properties 213 | dependency-reduced-pom.xml 214 | buildNumber.properties 215 | .mvn/timing.properties 216 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 217 | .mvn/wrapper/maven-wrapper.jar 218 | 219 | # Eclipse m2e generated files 220 | # Eclipse Core 221 | .project 222 | # JDT-specific (Eclipse Java Development Tools) 223 | .classpath 224 | 225 | ### VisualStudioCode ### 226 | .vscode/* 227 | !.vscode/settings.json 228 | !.vscode/tasks.json 229 | !.vscode/launch.json 230 | !.vscode/extensions.json 231 | !.vscode/*.code-snippets 232 | 233 | # Local History for Visual Studio Code 234 | .history/ 235 | 236 | # Built Visual Studio Code Extensions 237 | *.vsix 238 | 239 | ### VisualStudioCode Patch ### 240 | # Ignore all local history of files 241 | .history 242 | .ionide 243 | 244 | # Support for Project snippet scope 245 | .vscode/*.code-snippets 246 | 247 | # Ignore code-workspaces 248 | *.code-workspace 249 | 250 | # End of https://www.toptal.com/developers/gitignore/api/java,maven,eclipse,intellij,visualstudiocode 251 | .vscode/launch.json 252 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | # Zeppelin ignored files 10 | /ZeppelinRemoteNotebooks/ 11 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.6"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/PwrApiApplication.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi; 2 | 3 | import java.io.IOException; 4 | 5 | import com.fasterxml.jackson.core.exc.StreamWriteException; 6 | import com.fasterxml.jackson.databind.DatabindException; 7 | 8 | import org.springframework.boot.SpringApplication; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | 11 | @SpringBootApplication 12 | public class PwrApiApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(PwrApiApplication.class, args); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/api/EdukacjaAPI.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.api; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | import dev.wms.pwrapi.entity.edukacja.Subject; 7 | import dev.wms.pwrapi.scrapper.edukacja.EduScrapperServices; 8 | import dev.wms.pwrapi.service.edukacja.EduService; 9 | import io.swagger.v3.oas.annotations.Operation; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestParam; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | @RestController 19 | @RequestMapping(value = "/api/edukacja", produces = "application/json") 20 | public class EdukacjaAPI { 21 | 22 | private EduService edukacjaService; 23 | 24 | @Autowired 25 | public EdukacjaAPI(EduService edukacjaService){ 26 | this.edukacjaService = edukacjaService; 27 | } 28 | 29 | @GetMapping("/wektor") 30 | @Operation(summary = "Return available group for user's most recent enrollments", 31 | description = "This endpoint is probably going to be deprecated, because of migration of enrollment system to USOS. " + 32 | "It's implementation is slow and based on Selenium, rather than scraping HTTP requests") 33 | public ResponseEntity> getAvailableGroups(@RequestParam("login") String login, @RequestParam("password") String password ) throws IOException { 34 | List response = edukacjaService.doFetchSubjects(login, password); 35 | return ResponseEntity.status(HttpStatus.OK).body(response); 36 | } 37 | 38 | @GetMapping 39 | @Operation(summary = "Checks if login and password can be used to login to edukacja.cl", 40 | description = "Just a simple endpoint. You can use it to validate data and save it for later") 41 | public void loginToEdukacja(@RequestParam("login") String login, @RequestParam("password") String password) throws IOException{ 42 | EduScrapperServices.fetchHTMLConnectionDetails(login, password); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/api/EportalAPI.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.api; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | 8 | import dev.wms.pwrapi.entity.eportal.MarkSummary; 9 | import dev.wms.pwrapi.entity.eportal.calendar.CalendarMonth; 10 | import dev.wms.pwrapi.dto.eportal.sections.EportalSection; 11 | import dev.wms.pwrapi.service.eportal.EportalService; 12 | import io.swagger.v3.oas.annotations.Operation; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.http.HttpStatus; 15 | import org.springframework.http.ResponseEntity; 16 | import org.springframework.web.bind.annotation.GetMapping; 17 | import org.springframework.web.bind.annotation.PathVariable; 18 | import org.springframework.web.bind.annotation.RequestMapping; 19 | import org.springframework.web.bind.annotation.RequestParam; 20 | import org.springframework.web.bind.annotation.RestController; 21 | 22 | import dev.wms.pwrapi.utils.eportal.exceptions.WrongCourseIdException; 23 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 24 | 25 | import javax.validation.constraints.Max; 26 | import javax.validation.constraints.Min; 27 | 28 | @RestController 29 | @RequestMapping(value = "/api/eportal", produces = "application/json") 30 | public class EportalAPI { 31 | 32 | private EportalService eService; 33 | 34 | @Autowired 35 | public EportalAPI(EportalService eService){ 36 | this.eService = eService; 37 | } 38 | 39 | @GetMapping() 40 | @Operation(summary = "Validates ePortal login data", description = "Can be used to cache login and password for later API usage") 41 | public void getEportalData(@RequestParam String login, @RequestParam String password) throws JsonProcessingException, IOException, LoginException { 42 | eService.getEportalData(login, password); 43 | } 44 | 45 | @GetMapping("/kursy") 46 | @Operation(summary = "Returns all courses of the given user") 47 | public ResponseEntity getEportalKursy(@RequestParam String login, @RequestParam String password) throws IOException, LoginException { 48 | 49 | String result = eService.getEportalKursy(login, password); 50 | 51 | return ResponseEntity.status(HttpStatus.OK).body(result); 52 | } 53 | 54 | @GetMapping("/kurs/{id}/sekcje") 55 | @Operation(summary = "Returns all sections for the given course", description = "You can fetch the course ID using /kursy endpoint") 56 | public ResponseEntity> getEportalSekcje(@RequestParam String login, @RequestParam String password, @PathVariable int id) throws JsonProcessingException, IOException, LoginException, WrongCourseIdException { 57 | 58 | return ResponseEntity.status(HttpStatus.OK).body(eService.getEportalSekcje(login, password, id)); 59 | } 60 | 61 | 62 | @GetMapping("/kursy/{id}/oceny") 63 | @Operation(summary = "Returns all marks for the given course", description = "You can fetch the course ID using /kursy endpoint") 64 | public ResponseEntity> getEportalOceny(@RequestParam String login, @RequestParam String password, @PathVariable int id) throws JsonProcessingException { 65 | 66 | return ResponseEntity.status(HttpStatus.OK).body(eService.getEportalOceny(login, password, id)); 67 | } 68 | 69 | 70 | @GetMapping("/kalendarz") 71 | @Operation(summary = "Returns events that take place in month with offset", description = "Max offset is from -10 to 10") 72 | public ResponseEntity getEportalKalendarzMiesiac(@RequestParam String login, @RequestParam String password, 73 | @RequestParam(defaultValue = "0") @Min(-10) @Max(10) int offset) throws IOException { 74 | 75 | return ResponseEntity.status(HttpStatus.OK).body(eService.getEportalKalendarzOffset(login, password, offset)); 76 | } 77 | 78 | 79 | @GetMapping("/kalendarz/pobierz") 80 | @Operation(summary = "Returns calendar in ICS format", description = "Calendar range is 60 days back and forth") 81 | public ResponseEntity getEportalICS(@RequestParam String login, @RequestParam String password) throws IOException { 82 | 83 | return ResponseEntity.status(HttpStatus.OK).body(eService.getEportalKalendarzIcsLink(login, password)); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/api/NewsAPI.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.api; 2 | 3 | import dev.wms.pwrapi.dto.news.Channel; 4 | import dev.wms.pwrapi.dto.news.FacultyType; 5 | import dev.wms.pwrapi.service.news.NewsService; 6 | import io.swagger.v3.oas.annotations.Operation; 7 | import lombok.AllArgsConstructor; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestParam; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | 15 | @RestController 16 | @RequestMapping(value = "/api/news", produces = "application/json") 17 | @AllArgsConstructor 18 | public class NewsAPI { 19 | 20 | private NewsService newsService; 21 | 22 | @GetMapping("/general") 23 | @Operation(summary = "Returns recent news from main PWr website", 24 | description = "This endpoint implementation is based on RSS scraping, transforming and caching. " + 25 | "RSS is taken from https://pwr.edu.pl/rss/pl/24.xml and which, as we observed, is a copy of news available on " + 26 | "https://pwr.edu.pl/uczelnia/aktualnosci The data is cached for 15 minutes from last call, so recent news can be displayed with maximum 15 " + 27 | "minutes delay.") 28 | public ResponseEntity fetchGeneralNews(){ 29 | return ResponseEntity.ok(newsService.fetchGeneralNews()); 30 | } 31 | 32 | @GetMapping("/faculty") 33 | @Operation(summary = "Returns recent news from faculty website", 34 | description = "Implementation of this endpoint is based on RSS scraping or HTTP scraping. If the website supports RSS, " + 35 | "rss is used, if not, the traditional HTTP scraping and HTML parsing is used. Detailed info about website and " + 36 | "used method for certain faculties can be viewed here https://github.com/komp15/PWr-API/blob/feature_newsAPI/src/main/java/dev/wms/pwrapi/dto/news/FacultyType.java " + 37 | "The data is cached for 15 minutes from last call for all faculties, so recent news can be displayed with maximum 15 " + 38 | "minutes delay.") 39 | public ResponseEntity fetchFacultyNews( 40 | @RequestParam FacultyType faculty){ 41 | return ResponseEntity.ok(newsService.fetchNewsForFaculty(faculty)); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/api/ParkingAPI.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.api; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | 8 | import dev.wms.pwrapi.dto.parking.Parking; 9 | import dev.wms.pwrapi.dto.parking.ParkingWithHistory; 10 | import dev.wms.pwrapi.service.parking.ParkingService; 11 | import lombok.AllArgsConstructor; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import io.swagger.v3.oas.annotations.Operation; 19 | 20 | @RestController 21 | @RequestMapping(value="/api/parking", produces = "application/json") 22 | @AllArgsConstructor 23 | public class ParkingAPI { 24 | 25 | private ParkingService parkingService; 26 | 27 | @GetMapping 28 | @Operation(summary = "Returns processed data from skd.pwr.edu.pl", description = "You can use it to get data from skd.pwr.edu.pl in simple format") 29 | public ResponseEntity> getProcessedParkingInfo() throws JsonProcessingException, IOException{ 30 | List result = parkingService.getParkingData(); 31 | return ResponseEntity.status(HttpStatus.OK).body(result); 32 | 33 | } 34 | 35 | @GetMapping("/raw") 36 | @Operation(summary = "Returns history data from skd.pwr.edu.pl", 37 | description = "You can use it to get parking history data from last 24h") 38 | public ResponseEntity> getRawParkingInfo() throws IOException{ 39 | return ResponseEntity.status(HttpStatus.OK).body(parkingService.getRawParkingData()); 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/api/ProwadzacyAPI.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.api; 2 | 3 | import dev.wms.pwrapi.entity.prowadzacy.ProwadzacyResult; 4 | import dev.wms.pwrapi.service.prowadzacy.ProwadzacyService; 5 | import io.swagger.v3.oas.annotations.Operation; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.validation.annotation.Validated; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import javax.validation.constraints.Max; 13 | import javax.validation.constraints.Min; 14 | 15 | @RestController 16 | @RequestMapping(value = "/api/prowadzacy", produces="application/json") 17 | @Validated 18 | public class ProwadzacyAPI { 19 | 20 | private final ProwadzacyService prowadzacyService; 21 | 22 | @Autowired 23 | public ProwadzacyAPI(ProwadzacyService prowadzacyService){ 24 | this.prowadzacyService = prowadzacyService; 25 | } 26 | 27 | @GetMapping 28 | @Operation(summary = "Returns OK if website is reachable", description = "Mostly use for debugging issues") 29 | public void getWebsiteStatus(){ 30 | prowadzacyService.getWebsiteStatus(); 31 | } 32 | 33 | @GetMapping("/szukaj") 34 | @Operation(summary = "Returns teacher's plan", 35 | description = "Use query parameter to look for teacher you want to get plan of. " + 36 | "Please remember that we take only best matching result. For example if you want to " + 37 | "look for \"Dariusz Konieczny\", and you only query \"Konieczny\" you might end with result for " + 38 | "\"Jan Skonieczny\". query parameter is case-insensitive. You can also use offset value, " + 39 | "which returns you teacher's plan few weeks back and forth") 40 | public ResponseEntity getForTeacherQuery(@RequestParam String query, 41 | @RequestParam(defaultValue = "0") @Min(-20) @Max(20) int offset){ 42 | return ResponseEntity.status(HttpStatus.OK).body(prowadzacyService.getForTeacherQuery(query, offset)); 43 | } 44 | 45 | @GetMapping("/szukaj/sala") 46 | @Operation(summary = "Returns room's plan", description = "In order to use this endpoint you must provide a " + 47 | "very precise query. Please remember that building format is usually %LETTER%-%NUMBER% (for example D-20) Parameters are case-insensitive") 48 | 49 | public ResponseEntity getForRoomQuery(@RequestParam String building, 50 | @RequestParam String room){ 51 | return ResponseEntity.status(HttpStatus.OK).body(prowadzacyService.getForRoomQuery(building, room, null)); 52 | } 53 | 54 | @GetMapping("/szukaj/przedmiot") 55 | @Operation(summary = "Return's plan of all lessons in given course", description = "In order to use this endpoint you must provide a " + 56 | "very precise query. Parameters are case-insensitive, but must contain full subject name. For example query for \"Algorytmy i struktury dan\" would result in NoResultsException, or wrong results") 57 | public ResponseEntity getForSubjectQuery(@RequestParam String query){ 58 | return ResponseEntity.status(HttpStatus.OK).body(prowadzacyService.getForSubjectQuery(query, null)); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/edukacja/EduMessageDAOImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.edukacja; 2 | 3 | import dev.wms.pwrapi.scrapper.edukacja.EduScrapperServices; 4 | import dev.wms.pwrapi.dto.edukacja.EduConnection; 5 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 6 | import okhttp3.OkHttpClient; 7 | import okhttp3.Request; 8 | import okhttp3.Response; 9 | import org.jsoup.Jsoup; 10 | import org.jsoup.nodes.Document; 11 | 12 | import java.io.IOException; 13 | 14 | public class EduMessageDAOImpl { 15 | 16 | public static void fetchMessage(String login, String password) throws IOException, LoginException { 17 | 18 | EduConnection eduConnection = EduScrapperServices.fetchHTMLConnectionDetails(login, password); 19 | //eduConnection. 20 | 21 | String URL = "https://edukacja.pwr.wroc.pl/EdukacjaWeb/podgladWiadomosci.do?clEduWebSESSIONTOKEN=" + eduConnection.getSessionToken() + "==&event=positionRow&rowId=75792517&positionIterator=WiadomoscWSkrzynceViewIterator/WEB-INF/pages/secure/teksty/tekst.jsp"; 22 | //String URLIndeks = "https://edukacja.pwr.wroc.pl/EdukacjaWeb/indeks.do?clEduWebSESSIONTOKEN=" + eduConnection.getSessionToken() + "==&event=WyborSluchacza"; 23 | 24 | OkHttpClient client = new OkHttpClient().newBuilder() 25 | .build(); 26 | Request request = new Request.Builder() 27 | .url(URL) 28 | .method("GET", null) 29 | .addHeader("sec-ch-ua", "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"100\", \"Google Chrome\";v=\"100\"") 30 | .addHeader("sec-ch-ua-mobile", "?0") 31 | .addHeader("sec-ch-ua-platform", "\"Windows\"") 32 | .addHeader("Upgrade-Insecure-Requests", "1") 33 | .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36") 34 | .addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9") 35 | .addHeader("host", "edukacja.pwr.wroc.pl") 36 | .addHeader("Cookie", "JSESSIONID=" + eduConnection.getJsessionid()) 37 | .build(); 38 | Response response = client.newCall(request).execute(); 39 | 40 | String responseStr = response.body().string(); 41 | //System.out.println(responseStr); 42 | 43 | Document document = Jsoup.parse(responseStr); 44 | //String message = document.selectXpath("//*[@id=\"GORAPORTALU\"]/tbody/tr[4]/td/table/tbody/tr[1]/td[3]/table/tbody/tr/td/table[1]/tbody/tr[8]/td[2]").text(); 45 | //System.out.println(message); 46 | //*[@id="GORAPORTALU"]/tbody/tr[4]/td/table/tbody/tr[1]/td[3]/table/tbody/tr/td/table[1]/tbody/tr[8]/td[2]/text()[1] 47 | //System.out.println(document.selectXpath("/html/body/table/tbody/tr/td/table/tbody/tr[4]/td/table/tbody/tr[1]/td[3]/table/tbody/tr/td/table[4]")); 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/edukacja/EduSubjectDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.edukacja; 2 | 3 | import dev.wms.pwrapi.entity.edukacja.Subject; 4 | 5 | import java.util.ArrayList; 6 | 7 | public interface EduSubjectDAO { 8 | 9 | ArrayList doFetchSubjects(String login, String password); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/eportal/EportalCalendarDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.eportal; 2 | 3 | 4 | import dev.wms.pwrapi.entity.eportal.calendar.CalendarEvent; 5 | import dev.wms.pwrapi.entity.eportal.calendar.CalendarMonth; 6 | import dev.wms.pwrapi.scrapper.eportal.EportalScrapperService; 7 | import okhttp3.*; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jsoup.Jsoup; 10 | import org.jsoup.nodes.Document; 11 | import org.jsoup.nodes.Element; 12 | import org.springframework.stereotype.Repository; 13 | 14 | import java.io.IOException; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | @Repository 19 | public class EportalCalendarDAO { 20 | 21 | public CalendarMonth getEventsWithOffset(String login, String password, int offset) throws IOException { 22 | 23 | EportalScrapperService.loginToEportal(login, password); 24 | OkHttpClient client = EportalScrapperService.getClient(); 25 | 26 | Document page = getDocumentFromUrl(client, "https://eportal.pwr.edu.pl/calendar/view.php?view=month"); 27 | 28 | String buttonClassName; 29 | 30 | if(offset < 0){ 31 | buttonClassName = "arrow_link previous"; 32 | } else { 33 | buttonClassName = "arrow_link next"; 34 | } 35 | 36 | for(int i = 0; i < Math.abs(offset); i++){ 37 | 38 | String nextCalendarUrl = page.getElementsByClass(buttonClassName).first().attr("href"); 39 | 40 | page = getDocumentFromUrl(client, nextCalendarUrl); 41 | 42 | } 43 | 44 | String monthName = page.getElementsByClass("current").text(); 45 | 46 | List daysElement = page.getElementsByClass("day"); 47 | daysElement.removeIf(day -> day.getElementsByClass("eventname").text().equals("")); 48 | 49 | List events = new ArrayList<>(); 50 | 51 | for(Element day : daysElement) { 52 | 53 | String[] dateArray = day.getElementsByClass("sr-only").text().split(","); 54 | 55 | CalendarEvent event = CalendarEvent.builder() 56 | .title(day.getElementsByClass("eventname").text()) 57 | .date(dateArray[dateArray.length-2] + "," + dateArray[dateArray.length-1]) 58 | .build(); 59 | 60 | events.add(event); 61 | } 62 | 63 | 64 | return CalendarMonth.builder() 65 | .monthName(monthName) 66 | .events(events) 67 | .build(); 68 | 69 | } 70 | 71 | public String getIcsCalendarUrl(String login, String password) throws IOException { 72 | 73 | EportalScrapperService.loginToEportal(login, password); 74 | OkHttpClient client = EportalScrapperService.getClient(); 75 | 76 | Document page = getDocumentFromUrl(client, "https://eportal.pwr.edu.pl/calendar/export.php"); 77 | 78 | String sessionKey = page.getElementsByAttributeValue("name", "sesskey").attr("value"); 79 | 80 | MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); 81 | RequestBody body = RequestBody.create(mediaType, "_qf__core_calendar_export_form=1&events[exportevents]=all&generateurl=Pobierz adres URL kalendarza&period[timeperiod]=recentupcoming&sesskey=" + sessionKey); 82 | Request request = new Request.Builder() 83 | .url("https://eportal.pwr.edu.pl/calendar/export.php") 84 | .method("POST", body) 85 | 86 | .build(); 87 | 88 | Response response = client.newCall(request).execute(); 89 | 90 | 91 | String calendarURL = Jsoup.parse(response.body().string()) 92 | .getElementsByClass("calendarurl") 93 | .text() 94 | .replace("Adres URL kalendarza: ", ""); 95 | 96 | 97 | return calendarURL; 98 | } 99 | 100 | 101 | 102 | @NotNull 103 | private Document getDocumentFromUrl(OkHttpClient client, String nextCalendarUrl) throws IOException { 104 | Request request; 105 | Document page; 106 | request = new Request.Builder() 107 | .url(nextCalendarUrl) 108 | .build(); 109 | 110 | page = Jsoup.parse(client.newCall(request).execute().body().string()); 111 | return page; 112 | } 113 | 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/forum/ForumDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.forum; 2 | 3 | import dev.wms.pwrapi.entity.forum.Review; 4 | import dev.wms.pwrapi.entity.forum.Teacher; 5 | 6 | import java.util.List; 7 | 8 | public interface ForumDAO { 9 | int getNumberOfTeachers(); 10 | 11 | int getNumberOfReviews(); 12 | 13 | String getLastRefreshDate(); 14 | 15 | List fetchAllTeachers(); 16 | 17 | List fetchTeachersLimited(int limit); 18 | 19 | List fetchAllReviews(); 20 | 21 | List fetchReviewsLimited(int limit); 22 | 23 | List fetchTeacherReviewsById(int teacherId); 24 | 25 | List fetchTeacherReviewsByFullName(String firstName, String lastName); 26 | 27 | List fetchTeacherReviewsByIdLimited(int teacherId, int limit); 28 | 29 | List fetchTeacherReviewsByFullNameLimited(String firstName, String lastName, int limit); 30 | 31 | List fetchRecentTeacherReviewsByFullNameLimited(String firstName, String lastName, int limit); 32 | 33 | List fetchOldestTeacherReviewsByFullNameLimited(String firstName, String lastName, int limit); 34 | 35 | List fetchRecentTeacherReviewsByIdLimited(int teacherId, int limit); 36 | 37 | List fetchOldestTeacherReviewsByIdLimited(int teacherId, int limit); 38 | 39 | Teacher findTeacherById(int teacherId); 40 | 41 | Teacher findTeacherByName(String firstName, String lastName); 42 | 43 | Review findReviewById(int reviewId); 44 | 45 | List fetchBestRatedTeachersLimited(int limit); 46 | 47 | List fetchWorstOrBestTeachersByCategoryWithReviewsLimited(String category, int teacherLimit, int reviewLimit, boolean isBest); 48 | 49 | List fetchWorstRatedTeachersLimited(int limit); 50 | 51 | Teacher fetchTeacherByIdWithReviews(int teacherId); 52 | 53 | Teacher fetchTeacherByIdWithLimitedReviews(int teacherId, int limit); 54 | 55 | Teacher fetchTeacherByFullNameWithReviews(String firstName, String lastName); 56 | 57 | Teacher fetchTeacherByFullNameWithLimitedReviews(String firstName, String lastName, int limit); 58 | 59 | List getTeachersByCategory(String category); 60 | 61 | List getTeachersRankedByCategory(String category, boolean isAscending); 62 | 63 | List getTeachersRankedByCategoryLimited(String category, int limit, boolean isAscending); 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/jsos/JsosDataDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.jsos; 2 | 3 | import dev.wms.pwrapi.entity.jsos.finance.FinanceResult; 4 | import dev.wms.pwrapi.entity.jsos.finance.operations.FinanceOperationResult; 5 | import dev.wms.pwrapi.entity.jsos.messages.JsosMessageFull; 6 | import dev.wms.pwrapi.entity.jsos.messages.JsosMessageShort; 7 | import dev.wms.pwrapi.entity.jsos.marks.JsosSemester; 8 | import dev.wms.pwrapi.entity.jsos.JsosStudentData; 9 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 10 | 11 | import java.io.IOException; 12 | import java.util.List; 13 | 14 | public interface JsosDataDAO { 15 | 16 | /** 17 | * Returns all student's marks (limit is 200 semesters) 18 | * @param login Login used for JSOS 19 | * @param password Password used for JSOS 20 | * @return List of JsosSemester objects. Each of them contains marks for given semester 21 | * @throws IOException When some parsing goes wrong 22 | * @throws LoginException If password is wrong 23 | */ 24 | List getStudentMarks(String login, String password) 25 | throws IOException, LoginException; 26 | 27 | /** 28 | * Returns student data available in "Dane" JSOS's page 29 | * @param login Login used for JSOS 30 | * @param password Password used for JSOS 31 | * @return StudentData object, which contains personal information 32 | * @throws IOException When some parsing goes wrong 33 | * @throws LoginException If password is wrong 34 | */ 35 | JsosStudentData getStudentData(String login, String password) throws IOException, LoginException; 36 | 37 | /** 38 | * Return's student financial operations from /finanse page 39 | * @param login Login used for JSOS 40 | * @param password Password used for JSOS 41 | * @return FinanceOperationResult object containing list of all operations on given account 42 | * @throws IOException 43 | */ 44 | FinanceOperationResult getStudentFinanceOperations(String login, String password) throws IOException; 45 | FinanceResult getStudentFinance(String login, String password) throws IOException; 46 | /** 47 | * Returns value of student's message with given internal id's from a given page number 48 | * @param login Login used for JSOS 49 | * @param password Password used for JSOS 50 | * @param pageNumber Page number of messages interface 51 | * @param messageIds Internal ids of messages (can be fetched using general /wiadomosci endpoint) 52 | * @return List of JsosMessageFull objects (POJO) 53 | * @throws IOException When some parsing goes wrong 54 | */ 55 | List getStudentMessage(String login, String password, int pageNumber, Integer... messageIds) throws IOException; 56 | 57 | /** 58 | * Returns student's messages from given page number. Can be used to obtain message's internal ID 59 | * @param login Login used for JSOS 60 | * @param password Password used for JSOS 61 | * @param pageNumber Page number of messages interface 62 | * @return List of JsosMessageShort objects (POJO) 63 | * @throws IOException When some parsing goes wrong 64 | */ 65 | List getStudentMessages(String login, String password, int pageNumber) throws IOException; 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/jsos/JsosGeneralDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.jsos; 2 | 3 | import dev.wms.pwrapi.dto.jsos.JsosConnection; 4 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 5 | 6 | import java.io.IOException; 7 | 8 | public interface JsosGeneralDAO { 9 | /** 10 | * Login's to JSOS using Cookies. Method is using custom OkHttp's CookieJar implementation, which 11 | * swaps cookies for session cookies if needed. 12 | * @param login 13 | * @param password 14 | * @return 15 | * @throws IOException 16 | * @throws LoginException 17 | */ 18 | JsosConnection login(String login, String password) throws IOException, LoginException; 19 | 20 | /** 21 | * Return's client instance. Mostly used for logging in in JsosHttpUtils class and getting logged client instance 22 | * @return OkHttpClient instance 23 | */ 24 | okhttp3.OkHttpClient getClient(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/jsos/JsosGeneralDAOImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.jsos; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | import dev.wms.pwrapi.utils.http.HttpUtils; 7 | import org.jsoup.nodes.Document; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import dev.wms.pwrapi.dto.jsos.JsosConnection; 11 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 12 | import dev.wms.pwrapi.utils.jsos.cookies.CookieJarImpl; 13 | import lombok.Getter; 14 | import okhttp3.CookieJar; 15 | import okhttp3.MediaType; 16 | import okhttp3.OkHttpClient; 17 | import okhttp3.Request; 18 | import okhttp3.RequestBody; 19 | import okhttp3.Response; 20 | 21 | @Repository 22 | @Getter 23 | public class JsosGeneralDAOImpl implements JsosGeneralDAO { 24 | 25 | private OkHttpClient client; 26 | 27 | 28 | @Override 29 | public JsosConnection login(String login, String password) throws IOException, LoginException { 30 | 31 | CookieJar cookieJar = new CookieJarImpl(); 32 | JsosConnection jsosConnection = new JsosConnection(); 33 | 34 | client = new OkHttpClient.Builder() 35 | .cookieJar(cookieJar) 36 | .build(); 37 | 38 | Request request = new Request.Builder() 39 | .url("https://jsos.pwr.edu.pl/") 40 | .method("GET", null) 41 | .build(); 42 | 43 | Response response = client.newCall(request).execute(); 44 | List Cookielist = response.headers().values("Set-Cookie"); 45 | 46 | String jsessionid = (Cookielist.get(0).split(";"))[0].replace("JSOSSESSID=", ""); 47 | String YII_CSRF_TOKEN = (Cookielist.get(1).split(";"))[0].replace("YII_CSRF_TOKEN=", ""); 48 | 49 | 50 | jsosConnection.setSessionID(jsessionid); 51 | jsosConnection.setYII_CSRF_TOKEN(YII_CSRF_TOKEN); 52 | 53 | // get oauth details 54 | Document doc = HttpUtils.makeRequestWithClientAndGetDocument(client, 55 | "https://jsos.pwr.edu.pl/index.php/site/loginAsStudent"); 56 | 57 | String oauthConsumerKey = doc.select("input[name=oauth_consumer_key]").attr("value"); 58 | String oauthToken = doc.select("input[name=oauth_token]").attr("value"); 59 | 60 | jsosConnection.setOauthConsumerKey(oauthConsumerKey); 61 | jsosConnection.setOauthToken(oauthToken); 62 | 63 | //prepare request for logging in 64 | MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); 65 | RequestBody body = RequestBody.create(mediaType, 66 | "authenticateButton=Zaloguj&ida_hf_0=&oauth_callback_url=https://jsos.pwr.edu.pl/index.php/site/loginAsStudent" 67 | + 68 | "&oauth_consumer_key=" + jsosConnection.getOauthConsumerKey() + 69 | "&oauth_locale=pl" + 70 | "&oauth_request_url=http://oauth.pwr.edu.pl/oauth/authenticate&oauth_symbol=EIS" + 71 | "&oauth_token=" + jsosConnection.getOauthToken() + 72 | "&password=" + password + 73 | "&username=" + login); 74 | 75 | request = new Request.Builder() 76 | .url("https://oauth.pwr.edu.pl/oauth/authenticate?9-1.IFormSubmitListener-authenticateForm" + 77 | "&oauth_token=" + jsosConnection.getOauthToken() + 78 | "&oauth_consumer_key=" + jsosConnection.getOauthConsumerKey() + 79 | "&oauth_locale=pl") 80 | .method("POST", body) 81 | .addHeader("sec-ch-ua", 82 | "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"100\", \"Google Chrome\";v=\"100\"") 83 | .addHeader("sec-ch-ua-mobile", "?0") 84 | .addHeader("sec-ch-ua-platform", "\"Windows\"") 85 | .addHeader("Upgrade-Insecure-Requests", "1") 86 | .addHeader("Content-Type", "application/x-www-form-urlencoded") 87 | .addHeader("User-Agent", 88 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36") 89 | .addHeader("Accept", 90 | "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9") 91 | .addHeader("Sec-Fetch-Site", "same-origin") 92 | .addHeader("Sec-Fetch-Mode", "navigate") 93 | .addHeader("Sec-Fetch-User", "?1") 94 | .addHeader("Sec-Fetch-Dest", "document") 95 | .build(); 96 | 97 | response = client.newCall(request).execute(); 98 | 99 | String responseString = response.body().string(); 100 | response.body().close(); 101 | 102 | if(responseString.contains("Niepowodzenie logowania. Niepoprawna nazwa użytkownika lub hasło.")){ 103 | throw new LoginException(); 104 | } 105 | 106 | jsosConnection.setOauthSessionToken(((CookieJarImpl) cookieJar).getCookieStore() 107 | .get("oauth.pwr.edu.pl").toString().split(";")[0].replace("JSESSIONID=", "")); 108 | 109 | jsosConnection.setSessionID(((CookieJarImpl) cookieJar).getCookieStore() 110 | .get("jsos.pwr.edu.pl").get(2).toString().split(";")[0].replace("JSOSSESSID=", "")); 111 | 112 | return jsosConnection; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/jsos/JsosLessonsDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.jsos; 2 | 3 | import dev.wms.pwrapi.entity.jsos.JsosLesson; 4 | import dev.wms.pwrapi.entity.jsos.weeks.JsosDay; 5 | import dev.wms.pwrapi.entity.jsos.weeks.JsosWeek; 6 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 7 | import dev.wms.pwrapi.utils.jsos.exceptions.NoTodayClassException; 8 | 9 | import java.io.IOException; 10 | import java.util.List; 11 | 12 | public interface JsosLessonsDAO { 13 | /** 14 | * Returns today's student's today lessons 15 | * @param login Login for JSOS 16 | * @param password Password for JSOS 17 | * @return JsosDay object 18 | * @throws IOException If parsing goes wrong 19 | * @throws LoginException If logging in goes wrong 20 | * @throws NoTodayClassException If somehow there is now today day in JSOS 21 | */ 22 | JsosDay getTodaysLessons(String login, String password) throws IOException, LoginException, NoTodayClassException; 23 | 24 | /** 25 | * Returns tommorow's students lessons 26 | * @param login Login for JSOS 27 | * @param password Password for JSOS 28 | * @return JsosDay object 29 | * @throws IOException If parsing goes wrong 30 | * @throws LoginException If logging in goes wrong 31 | */ 32 | JsosDay getTomorrowLessons(String login, String password) throws IOException, LoginException; 33 | 34 | /** 35 | * Returns this week lessons 36 | * @param login Login for JSOS 37 | * @param password Password for JSOS 38 | * @return JsosWeek object 39 | * @throws IOException If parsing goes wrong 40 | * @throws LoginException If logging in goes wrong 41 | */ 42 | JsosWeek getThisWeekLessons(String login, String password) throws IOException, LoginException; 43 | /** 44 | * Returns next week lessons 45 | * @param login Login for JSOS 46 | * @param password Password for JSOS 47 | * @return JsosWeek object 48 | * @throws IOException If parsing goes wrong 49 | * @throws LoginException If logging in goes wrong 50 | */ 51 | JsosWeek getNextWeekLessons(String login, String password) throws IOException, LoginException; 52 | 53 | /** 54 | * Returns week lessons offseted by given offset (skips weeks back or forth in order to access the desired one) 55 | * @param login Login for JSOS 56 | * @param password Password for JSOS 57 | * @param offset How many weeks to go back or forth (supports also negative values for back forwarding) 58 | * @return JsosWeek object 59 | * @throws IOException If parsing goes wrong 60 | * @throws LoginException If logging in goes wrong 61 | */ 62 | 63 | JsosWeek getOffsetWeekLessons(String login, String password, int offset) throws IOException, LoginException; 64 | 65 | /** 66 | * Returns all students lessons (beware of even and odd weeks) 67 | * @param login Login for JSOS 68 | * @param password Password for JSOS 69 | * @return List of JsosLesson objects 70 | * @throws IOException If parsing goes wrong 71 | * @throws LoginException If logging in goes wrong 72 | */ 73 | List getAllLessons(String login, String password) throws IOException, LoginException; 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/news/NewsDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.news; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.DeserializationFeature; 5 | import com.fasterxml.jackson.dataformat.xml.XmlMapper; 6 | import dev.wms.pwrapi.dto.news.*; 7 | import dev.wms.pwrapi.utils.http.HttpUtils; 8 | import okhttp3.OkHttpClient; 9 | import org.jsoup.nodes.Document; 10 | import org.jsoup.nodes.Element; 11 | import org.jsoup.select.Elements; 12 | import org.springframework.stereotype.Repository; 13 | 14 | import java.time.LocalDate; 15 | import java.time.format.DateTimeFormatter; 16 | import java.util.List; 17 | import java.util.Locale; 18 | import java.util.regex.Matcher; 19 | import java.util.regex.Pattern; 20 | 21 | @Repository 22 | public class NewsDAO { 23 | 24 | private final DateTimeFormatter rssFormatter = DateTimeFormatter.ofPattern("dd MMM yyyy", Locale.ENGLISH); 25 | private final DateTimeFormatter goalFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); 26 | private final Pattern datePattern = Pattern.compile("\\d{2} [a-zA-Z]{3} \\d{4}"); 27 | 28 | public Channel parsePwrRSS(String rssUrl) { 29 | OkHttpClient client = new OkHttpClient(); 30 | String response = HttpUtils.makeRequestWithClientAndGetString(client, rssUrl); 31 | XmlMapper xmlMapper = new XmlMapper(); 32 | xmlMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 33 | xmlMapper.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true); 34 | xmlMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); 35 | xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 36 | 37 | try { 38 | Rss items = xmlMapper.readValue(response, Rss.class); 39 | for(Item item : items.getChannel().getItem()) reformatDate(item); 40 | 41 | return items.getChannel(); 42 | } catch (JsonProcessingException e) { 43 | throw new RuntimeException(e); 44 | } 45 | } 46 | 47 | private void reformatDate(Item item){ 48 | Matcher matcher = datePattern.matcher(item.getPubDate()); 49 | matcher.find(); 50 | LocalDate parsedDate = LocalDate.parse(matcher.group(), rssFormatter); 51 | item.setPubDate(parsedDate.format(goalFormatter)); 52 | } 53 | 54 | public Channel getFacultyNews(FacultyType faculty) { 55 | if(faculty.isRss){ 56 | return parsePwrRSS(faculty.url); 57 | } else { 58 | return parsePwrHTML(faculty.url); 59 | } 60 | } 61 | 62 | private Channel parsePwrHTML(String url) { 63 | OkHttpClient client = new OkHttpClient(); 64 | Document document = HttpUtils.makeRequestWithClientAndGetDocument(client, url); 65 | 66 | Elements newsBoxes = document.getElementsByClass("news-box"); 67 | newsBoxes.removeIf(box -> box.text().isEmpty()); 68 | 69 | List channelItems = newsBoxes.parallelStream() 70 | .map(newsBox -> parseItem(newsBox, url)) 71 | .toList(); 72 | 73 | 74 | return Channel.builder() 75 | .title(document.getElementsByClass("portal-title").first().text()) 76 | .link(url) 77 | .description("") 78 | .item(channelItems) 79 | .build(); 80 | } 81 | 82 | private Item parseItem(Element element, String url){ 83 | Element textDiv = element.getElementsByClass("col-text").first(); 84 | return Item.builder() 85 | .title(textDiv.getElementsByClass("title").first().attr("title")) 86 | .link(getDomainFromNewsUrl(url) + textDiv.getElementsByClass("title").first().attr("href")) 87 | .pubDate(textDiv.getElementsByClass("date").text().replace("Data: ","").strip() 88 | .split("Kategoria:")[0].strip()) 89 | .description(textDiv.getElementsByTag("p").get(1).text().replace("... więcej","") 90 | .replace("więcej","").strip()) 91 | .build(); 92 | } 93 | 94 | private String getDomainFromNewsUrl(String url){ 95 | return url.split(".pl")[0] + ".pl"; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/parking/ParkingDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.parking; 2 | 3 | import dev.wms.pwrapi.dto.parking.Parking; 4 | import dev.wms.pwrapi.dto.parking.ParkingWithHistory; 5 | 6 | import java.io.IOException; 7 | import java.util.List; 8 | 9 | public interface ParkingDAO { 10 | /** 11 | * Returns processed parking data. Server response is mapped to Parking objects. 12 | * @return List of parking objects 13 | * @throws IOException When deserialization goes wrong 14 | */ 15 | List getProcessedParkingInfo() throws IOException; 16 | 17 | /** 18 | * Returns parking information and array containing history of parking places for the last 24 hours 19 | * @return JSON Response from server 20 | * @throws IOException When deserialization goes wrong 21 | */ 22 | List getRawParkingData() throws IOException; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/parking/SKDParkingDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.parking; 2 | 3 | import java.io.IOException; 4 | import java.time.format.DateTimeFormatter; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | import dev.wms.pwrapi.dto.parking.ParkingWithHistory; 11 | import dev.wms.pwrapi.utils.http.HttpUtils; 12 | import dev.wms.pwrapi.utils.parking.ParkingDateUtils; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jsoup.nodes.Document; 15 | import org.jsoup.nodes.Element; 16 | import org.springframework.stereotype.Repository; 17 | 18 | import dev.wms.pwrapi.dto.parking.Parking; 19 | import okhttp3.OkHttpClient; 20 | 21 | @Repository 22 | public class SKDParkingDAO implements ParkingDAO { 23 | 24 | public static final String PARKING_WRONSKIEGO = "Parking Wrońskiego"; 25 | public static final String C_13 = "C13"; 26 | public static final String D_20 = "D20"; 27 | public static final String GEOCENTRUM = "Geocentrum"; 28 | public static final String ARCHITEKTURA = "Architektura"; 29 | 30 | @Override 31 | public List getProcessedParkingInfo() throws IOException{ 32 | return parseProcessed(fetchParkingWebsite()); 33 | } 34 | 35 | @Override 36 | public List getRawParkingData() throws IOException{ 37 | return parseWithDetails(fetchParkingWebsite()); 38 | } 39 | 40 | private Document fetchParkingWebsite() throws IOException { 41 | OkHttpClient client = new OkHttpClient().newBuilder() 42 | .build(); 43 | return HttpUtils.makeRequestWithClientAndGetDocument(client, "https://skd.pwr.edu.pl/"); 44 | } 45 | 46 | private List parseProcessed(Element page){ 47 | List result = new ArrayList<>(); 48 | Matcher matcher = Pattern.compile("\"type\":\"put\",\"key\":\"text\",\"feat\":7,\"value\":\"\\d+").matcher(page.html()); 49 | matcher.find(); 50 | result.add(new Parking(PARKING_WRONSKIEGO, getMeasurmentTime(), getPlacesFromResponse(matcher), 0)); 51 | matcher.find(); 52 | result.add(new Parking(C_13, getMeasurmentTime(), getPlacesFromResponse(matcher), 0)); 53 | matcher.find(); 54 | result.add(new Parking(D_20, getMeasurmentTime(), getPlacesFromResponse(matcher), 0)); 55 | matcher.find(); 56 | result.add(new Parking(GEOCENTRUM, getMeasurmentTime(), getPlacesFromResponse(matcher), 0)); 57 | matcher.find(); 58 | result.add(new Parking(ARCHITEKTURA, getMeasurmentTime(), getPlacesFromResponse(matcher), 0)); 59 | 60 | return result; 61 | } 62 | 63 | private List parseWithDetails(Element page){ 64 | List result = new ArrayList<>(); 65 | Matcher matcher = Pattern.compile("(?<=\\\\\"data\\\\\":\\[)(.*?)(?=\\])").matcher(page.html()); 66 | matcher.find(); 67 | result.add(new ParkingWithHistory(PARKING_WRONSKIEGO, getMeasurmentTime(), sanitizeArray(matcher.group()))); 68 | matcher.find(); 69 | result.add(new ParkingWithHistory(C_13, getMeasurmentTime(), sanitizeArray(matcher.group()))); 70 | matcher.find(); 71 | result.add(new ParkingWithHistory(D_20, getMeasurmentTime(), sanitizeArray(matcher.group()))); 72 | matcher.find(); 73 | result.add(new ParkingWithHistory(GEOCENTRUM, getMeasurmentTime(), sanitizeArray(matcher.group()))); 74 | matcher.find(); 75 | result.add(new ParkingWithHistory(ARCHITEKTURA, getMeasurmentTime(), sanitizeArray(matcher.group()))); 76 | 77 | return result; 78 | } 79 | 80 | private String sanitizeArray(String array){ 81 | return "[" + array + "]"; 82 | } 83 | 84 | @NotNull 85 | private String getMeasurmentTime() { 86 | return ParkingDateUtils.getDateTimeInPoland() 87 | .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); 88 | } 89 | 90 | private int getPlacesFromResponse(Matcher matcher) { 91 | return Integer.parseInt(matcher.group().split("value\":\"")[1]); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dao/prowadzacy/ProwadzacyDAO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dao.prowadzacy; 2 | 3 | import dev.wms.pwrapi.entity.prowadzacy.ProwadzacyResult; 4 | 5 | public interface ProwadzacyDAO { 6 | /** 7 | * Checks if website is reachable from API host 8 | * @return OK if connection is accessible (working on DTO for health endpoints) 9 | */ 10 | String connectToWebsite(); 11 | 12 | /** 13 | * Returns plan for given teacher 14 | * @param query Teacher name or surname which will be queried on prowadzacy server 15 | * @param offset Offset in weeks back (+) or forth (-) 16 | * @return DTO ProwadzacyResult consisting of lessons of given teacher 17 | */ 18 | ProwadzacyResult getPlanForTeacherQuery(String query, Integer offset); 19 | 20 | /** 21 | * Returns plan for given room. Please be careful when querying, because due to host architecture, 22 | * very precise query is needed 23 | * @param building Building you want to query in, for example D-20 24 | * @param room Room in the given building 25 | * @param offset Offset in weeks back (+) or forth (-) 26 | * @return DTO ProwadzacyResult consisting of lessons that take place in given room 27 | */ 28 | ProwadzacyResult getPlanForRoomQuery(String building, String room, Integer offset); 29 | 30 | /** 31 | * Returns plan of given subject. Please be aware, that this endpoint needs really precise query and won't 32 | * work on any spelling mistakes (for ex. Algorytmy i struktury dany) wont work due to mising "ch" 33 | * @param query Name of the subject 34 | * @param offset Offset in weeks back (+) or forth (-) 35 | * @return DTO ProwadzacyResult consisting of lessons in given subject (few can take place at one time) 36 | */ 37 | ProwadzacyResult getPlanForSubjectQuery(String query, Integer offset); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/ExceptionMessagingDTO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | import java.time.format.DateTimeFormatter; 7 | 8 | /** 9 | * This class is used for formatting exceptions that are thrown by our API 10 | */ 11 | @Data 12 | public class ExceptionMessagingDTO { 13 | private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); 14 | private String timestamp; 15 | private String errorMessage; 16 | private String documentation; 17 | 18 | public ExceptionMessagingDTO(String message){ 19 | this.timestamp = LocalDateTime.now().format(dateFormat); 20 | this.errorMessage = message; 21 | this.documentation = "https://pwr-api-dev.azurewebsites.net/swagger-ui/index.html"; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/edukacja/EduConnection.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.edukacja; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | 10 | @Getter 11 | @Setter 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @ToString 16 | public class EduConnection { 17 | 18 | private String sessionToken; 19 | private String webToken; 20 | private String jsessionid; 21 | 22 | 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/eportal/courseTitle.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.eportal; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class courseTitle { 13 | 14 | private String wydzial; 15 | private String nazwa; 16 | private String detailsLink; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/eportal/deserialization/Data.java: -------------------------------------------------------------------------------- 1 | 2 | package dev.wms.pwrapi.dto.eportal.deserialization; 3 | 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import javax.annotation.Generated; 8 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 9 | import com.fasterxml.jackson.annotation.JsonAnySetter; 10 | import com.fasterxml.jackson.annotation.JsonIgnore; 11 | import com.fasterxml.jackson.annotation.JsonInclude; 12 | import com.fasterxml.jackson.annotation.JsonProperty; 13 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 14 | 15 | 16 | @JsonInclude(JsonInclude.Include.NON_NULL) 17 | @JsonPropertyOrder({ 18 | "courses", 19 | "nextoffset" 20 | }) 21 | @Generated("jsonschema2pojo") 22 | @lombok.ToString 23 | public class Data { 24 | 25 | @JsonProperty("courses") 26 | private List courses = null; 27 | @JsonProperty("nextoffset") 28 | private Integer nextoffset; 29 | @JsonIgnore 30 | private Map additionalProperties = new HashMap(); 31 | 32 | @JsonProperty("courses") 33 | public List getCourses() { 34 | return courses; 35 | } 36 | 37 | @JsonProperty("courses") 38 | public void setCourses(List courses) { 39 | this.courses = courses; 40 | } 41 | 42 | @JsonProperty("nextoffset") 43 | public Integer getNextoffset() { 44 | return nextoffset; 45 | } 46 | 47 | @JsonProperty("nextoffset") 48 | public void setNextoffset(Integer nextoffset) { 49 | this.nextoffset = nextoffset; 50 | } 51 | 52 | @JsonAnyGetter 53 | public Map getAdditionalProperties() { 54 | return this.additionalProperties; 55 | } 56 | 57 | @JsonAnySetter 58 | public void setAdditionalProperty(String name, Object value) { 59 | this.additionalProperties.put(name, value); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/eportal/deserialization/Root.java: -------------------------------------------------------------------------------- 1 | 2 | package dev.wms.pwrapi.dto.eportal.deserialization; 3 | 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import javax.annotation.Generated; 7 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 8 | import com.fasterxml.jackson.annotation.JsonAnySetter; 9 | import com.fasterxml.jackson.annotation.JsonIgnore; 10 | import com.fasterxml.jackson.annotation.JsonInclude; 11 | import com.fasterxml.jackson.annotation.JsonProperty; 12 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 13 | 14 | 15 | 16 | @JsonInclude(JsonInclude.Include.NON_NULL) 17 | @JsonPropertyOrder({ 18 | "error", 19 | "data" 20 | }) 21 | @Generated("jsonschema2pojo") 22 | @lombok.ToString 23 | public class Root { 24 | 25 | @JsonProperty("error") 26 | private Boolean error; 27 | @JsonProperty("data") 28 | private Data data; 29 | @JsonIgnore 30 | private Map additionalProperties = new HashMap(); 31 | 32 | @JsonProperty("error") 33 | public Boolean getError() { 34 | return error; 35 | } 36 | 37 | @JsonProperty("error") 38 | public void setError(Boolean error) { 39 | this.error = error; 40 | } 41 | 42 | @JsonProperty("data") 43 | public Data getData() { 44 | return data; 45 | } 46 | 47 | @JsonProperty("data") 48 | public void setData(Data data) { 49 | this.data = data; 50 | } 51 | 52 | @JsonAnyGetter 53 | public Map getAdditionalProperties() { 54 | return this.additionalProperties; 55 | } 56 | 57 | @JsonAnySetter 58 | public void setAdditionalProperty(String name, Object value) { 59 | this.additionalProperties.put(name, value); 60 | } 61 | 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/eportal/sections/EportalElementType.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.eportal.sections; 2 | 3 | public enum EportalElementType { 4 | 5 | LINK, 6 | PDF, 7 | ARCHIWUM, 8 | REZERWACJA, 9 | QUIZ, 10 | ZADANIE, 11 | PREZENTACJA, 12 | PLIK, 13 | INNE 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/eportal/sections/EportalSection.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.eportal.sections; 2 | 3 | import java.util.ArrayList; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | @Data 11 | @Builder 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class EportalSection { 15 | 16 | private String sectionName; 17 | private ArrayList elements; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/eportal/sections/EportalSectionElement.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.eportal.sections; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class EportalSectionElement { 13 | 14 | 15 | 16 | private String title; 17 | private String type; 18 | 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/eportal/userDetails.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.eportal; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class userDetails { 13 | 14 | private String username; 15 | private int userID; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/jsos/JsosConnection.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.jsos; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | 9 | @Getter 10 | @Setter 11 | @Builder 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class JsosConnection { 15 | 16 | private String sessionID; 17 | private String oauthConsumerKey; 18 | private String oauthToken; 19 | private String YII_CSRF_TOKEN; 20 | private String oauthSessionToken; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/news/Channel.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.news; 2 | 3 | import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.List; 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class Channel { 16 | public String title; 17 | public String link; 18 | public String description; 19 | @JacksonXmlElementWrapper(useWrapping = false) 20 | public List item; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/news/FacultyType.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.news; 2 | 3 | public enum FacultyType { 4 | 5 | INFORMATYKI_I_TELEKOMUNIKACJI("https://wit.pwr.edu.pl/rss/pl/189.xml", true), 6 | ZARZADZANIA("https://wz.pwr.edu.pl/rss/pl/127.xml", true), 7 | ELEKTRONIKI_MIKROSYSTEMOW_I_FOTONIKI("https://wefim.pwr.edu.pl/rss/pl/5.xml", true), 8 | ARCHITEKTURY("https://wa.pwr.edu.pl/o-wydziale/aktualnosci", false), 9 | BUDOWNICTWA_LADOWEGO_I_WODNEGO("https://wbliw.pwr.edu.pl/o-wydziale/aktualnosci", false), 10 | CHEMICZNY("https://wch.pwr.edu.pl/o-wydziale/aktualnosci", false), 11 | ELEKTRYCZNY("https://weny.pwr.edu.pl/o-wydziale/aktualnosci", false), 12 | GEOINZYNIERII_GORNICTWA_I_GEOLOGII("https://wggg.pwr.edu.pl/o-wydziale/aktualnosci", false), 13 | INZYNIERII_SRODOWISKA("https://wis.pwr.edu.pl/o-wydziale/aktualnosci", false), 14 | MECHANICZNO_ENERGETYCZNY("https://wme.pwr.edu.pl/aktualnosci", false), 15 | MECHANICZNY("https://wm.pwr.edu.pl/o-wydziale/aktualnosci", false), 16 | PODSTAWOWYCH_PROBLEMOW_TECHNIKI("https://wppt.pwr.edu.pl/o-wydziale/aktualnosci", false), 17 | MATEMATYKI("https://wmat.pwr.edu.pl/o-wydziale/aktualnosci", false), 18 | FILIA_POLITECHNIKI_WROCLAWSKIEJ_W_JELENIEJ_GORZE("https://jelenia-gora.pwr.edu.pl/o-filii/aktualnosci", false), 19 | FILIA_POLITECHNIKI_WROCLAWSKIEJ_W_WALBRZYCHU("https://walbrzych.pwr.edu.pl/o-filii/aktualnosci", false), 20 | FILIA_POLITECHNIKI_WROCLAWSKIEJ_W_LEGNICY("https://legnica.pwr.edu.pl/o-wydziale/aktualnosci", false); 21 | 22 | 23 | 24 | public final String url; 25 | public final boolean isRss; 26 | 27 | FacultyType(String url, boolean isRss) { 28 | this.url = url; 29 | this.isRss = isRss; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/news/Item.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.news; 2 | 3 | import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | @Data 11 | @Jacksonized 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class Item { 16 | public String title; 17 | public String link; 18 | public String pubDate; 19 | public String description; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/news/Rss.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.news; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class Rss { 11 | public Channel channel; 12 | public double version; 13 | public String text; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/DataWithLabels.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class DataWithLabels { 9 | private List labels; 10 | private List data; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/IParkingResponse.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class IParkingResponse { 7 | private int success; 8 | private DataWithLabels slots; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/Parking.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class Parking { 13 | 14 | 15 | private String name; 16 | private String lastUpdate; 17 | private int leftPlaces; 18 | private int trend; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/ParkingWithHistory.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | @Data 8 | @Builder 9 | @AllArgsConstructor 10 | public class ParkingWithHistory { 11 | private String name; 12 | private String lastUpdate; 13 | private String history; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/deserialization/ParkingArrayElement.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking.deserialization; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | 8 | 9 | import lombok.AllArgsConstructor; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import lombok.ToString; 13 | 14 | 15 | @Data 16 | @ToString 17 | @AllArgsConstructor 18 | @JsonIgnoreProperties(ignoreUnknown = true) 19 | @NoArgsConstructor 20 | public class ParkingArrayElement { 21 | 22 | @JsonProperty("id") 23 | private String id; 24 | @JsonProperty("parking_id") 25 | private String parking_id; 26 | @JsonProperty("czas_pomiaru") 27 | private String czas_pomiaru; 28 | @JsonProperty("liczba_miejsc") 29 | private String liczba_miejsc; 30 | @JsonProperty("trend") 31 | private String trend; 32 | @JsonProperty("nazwa") 33 | private String nazwa; 34 | @JsonProperty("symbol") 35 | private String symbol; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/deserialization/ParkingResponse.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking.deserialization; 2 | 3 | import java.util.List; 4 | 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import lombok.ToString; 10 | 11 | @ToString 12 | @Data 13 | @NoArgsConstructor 14 | public class ParkingResponse { 15 | 16 | @JsonProperty("success") 17 | private int success; 18 | @JsonProperty("places") 19 | private List places; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/deserialization/ParkingWithHistoryArrayElement.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking.deserialization; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public 7 | class ParkingWithHistoryArrayElement { 8 | private String id; 9 | private String parking_id; 10 | private String czas_pomiaru; 11 | private String liczba_miejsc; 12 | private String trend; 13 | private ParkingWithHistoryChart chart; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/deserialization/ParkingWithHistoryChart.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking.deserialization; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | public class ParkingWithHistoryChart { 10 | @JsonProperty("x") 11 | private List x; 12 | @JsonProperty("data") 13 | private List data; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/dto/parking/deserialization/ParkingWithHistoryResponse.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.dto.parking.deserialization; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import dev.wms.pwrapi.dto.parking.DataWithLabels; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class ParkingWithHistoryResponse { 12 | private int success; 13 | private DataWithLabels slots; 14 | @JsonIgnore 15 | private Integer parkingId; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/edukacja/Group.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.edukacja; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.NoArgsConstructor; 6 | import lombok.ToString; 7 | 8 | @AllArgsConstructor 9 | @Builder 10 | @ToString 11 | @NoArgsConstructor 12 | public class Group { 13 | 14 | String groupName; 15 | String teacher; 16 | String date; 17 | String form; 18 | String code; 19 | 20 | 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | public void setCode(String code) { 26 | this.code = code; 27 | } 28 | public String getGroupName() { 29 | return groupName; 30 | } 31 | public void setGroupName(String groupName) { 32 | this.groupName = groupName; 33 | } 34 | public String getTeacher() { 35 | return teacher; 36 | } 37 | public void setTeacher(String teacher) { 38 | this.teacher = teacher; 39 | } 40 | public String getDate() { 41 | return date; 42 | } 43 | public void setDate(String date) { 44 | this.date = date; 45 | } 46 | public String getForm() { 47 | return form; 48 | } 49 | public void setForm(String form) { 50 | this.form = form; 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/edukacja/Subject.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.edukacja; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Subject { 6 | 7 | String id; 8 | String name; 9 | ArrayList groups = new ArrayList(); 10 | String groupsLink; 11 | public String getId() { 12 | return id; 13 | } 14 | public void setId(String id) { 15 | this.id = id; 16 | } 17 | public String getName() { 18 | return name; 19 | } 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | public ArrayList getGroups() { 24 | return groups; 25 | } 26 | public void setGroups(ArrayList groups) { 27 | this.groups = groups; 28 | } 29 | 30 | public String getGroupsLink() { 31 | return groupsLink; 32 | } 33 | public void setGroupsLink(String groupsLink) { 34 | this.groupsLink = groupsLink; 35 | } 36 | @Override 37 | public String toString() { 38 | return "Subject [groupsLink=" + groupsLink.substring(0,20) + "..." + ", id=" + id + ", name=" + name + "]"; 39 | } 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/eportal/Mark.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.eportal; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class Mark { 9 | 10 | private String name; 11 | private String weight; 12 | private String value; 13 | private String range; 14 | private String percentage; 15 | private String markName; 16 | private String feedback; 17 | private String courseParticipation; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/eportal/MarkSummary.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.eportal; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Data 9 | public class MarkSummary { 10 | 11 | private String courseName; 12 | private List marks = new ArrayList<>(); 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/eportal/calendar/CalendarEvent.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.eportal.calendar; 2 | 3 | 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | @Data 8 | @Builder 9 | public class CalendarEvent { 10 | 11 | private String title; 12 | private String date; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/eportal/calendar/CalendarMonth.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.eportal.calendar; 2 | 3 | 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @Builder 11 | public class CalendarMonth { 12 | 13 | private String monthName; 14 | private List events; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/forum/Review.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.forum; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | 5 | // review won't exist without teacher 6 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 7 | public class Review { 8 | 9 | private int id; 10 | private String courseName; 11 | private double givenRating; 12 | private String title; 13 | private String review; 14 | private String reviewer; 15 | private String postDate; 16 | private Teacher teacher; 17 | 18 | public Review(){ 19 | 20 | } 21 | 22 | public Teacher getTeacher() { 23 | return teacher; 24 | } 25 | 26 | public void setTeacher(Teacher teacher) { 27 | this.teacher = teacher; 28 | } 29 | 30 | public int getId() { 31 | return id; 32 | } 33 | 34 | public void setId(int id) { 35 | this.id = id; 36 | } 37 | 38 | public String getCourseName() { 39 | return courseName; 40 | } 41 | 42 | public void setCourseName(String courseName) { 43 | this.courseName = courseName; 44 | } 45 | 46 | public double getGivenRating() { 47 | return givenRating; 48 | } 49 | 50 | public void setGivenRating(double givenRating) { 51 | this.givenRating = givenRating; 52 | } 53 | 54 | public String getTitle() { 55 | return title; 56 | } 57 | 58 | public void setTitle(String title) { 59 | this.title = title; 60 | } 61 | 62 | public String getReview() { 63 | return review; 64 | } 65 | 66 | public void setReview(String review) { 67 | this.review = review; 68 | } 69 | 70 | public String getReviewer() { 71 | return reviewer; 72 | } 73 | 74 | public void setReviewer(String reviewer) { 75 | this.reviewer = reviewer; 76 | } 77 | 78 | public String getPostDate() { 79 | return postDate; 80 | } 81 | 82 | public void setPostDate(String postDate) { 83 | this.postDate = postDate; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/forum/Teacher.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.forum; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 9 | public class Teacher { 10 | 11 | private int id; 12 | private String category; 13 | private String academicTitle; 14 | private String fullName; 15 | private double average; 16 | private List reviews; 17 | 18 | public Teacher(){ 19 | this.reviews = new ArrayList<>(); 20 | } 21 | 22 | public Teacher(int id, String category, String academicTitle, String fullName, double average) { 23 | this.id = id; 24 | this.category = category; 25 | this.academicTitle = academicTitle; 26 | this.fullName = fullName; 27 | this.average = average; 28 | this.reviews = new ArrayList<>(); 29 | } 30 | 31 | public void addReview(Review review){ 32 | reviews.add(review); 33 | } 34 | 35 | public List getReviews() { 36 | return reviews; 37 | } 38 | 39 | public void setReviews(ArrayList reviews) { 40 | this.reviews = reviews; 41 | } 42 | 43 | public String getCategory() { 44 | return category; 45 | } 46 | 47 | public void setCategory(String category) { 48 | this.category = category; 49 | } 50 | 51 | public int getId() { 52 | return id; 53 | } 54 | 55 | public void setId(int id) { 56 | this.id = id; 57 | } 58 | 59 | public String getAcademicTitle() { 60 | return academicTitle; 61 | } 62 | 63 | public void setAcademicTitle(String academicTitle) { 64 | this.academicTitle = academicTitle; 65 | } 66 | 67 | public String getFullName() { 68 | return fullName; 69 | } 70 | 71 | public void setFullName(String fullName) { 72 | this.fullName = fullName; 73 | } 74 | 75 | public double getAverage() { 76 | return average; 77 | } 78 | 79 | public void setAverage(double average) { 80 | this.average = average; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/JsosLesson.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class JsosLesson { 13 | 14 | private String idKursu; 15 | private String nazwaKursu; 16 | private String prowadzacy; 17 | private String kodGrupy; 18 | private String termin; 19 | private String godziny; 20 | private String ects; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/JsosStudentData.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | @lombok.Builder 13 | public class JsosStudentData { 14 | 15 | private String wydzial; 16 | private String kierunek; 17 | private String specjalnosc; 18 | private String stopien; 19 | private String numberAlbumu; 20 | private String imiona; 21 | private String nazwisko; 22 | private String imieOjca; 23 | private String dataUrodzenia; 24 | private String miejsceUrodzenia; 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/finance/FinanceEntry.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.finance; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class FinanceEntry { 9 | 10 | private String dataNaliczenia; 11 | private String amount; 12 | private String name; 13 | private String rata; 14 | private String terminPlatnosci; 15 | private String status; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/finance/FinanceResult.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.finance; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | @Builder 10 | public class FinanceResult { 11 | 12 | private String sumOfRequiredPayments; 13 | private List entries; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/finance/operations/FinanceOperationResult.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.finance.operations; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | @Builder 10 | public class FinanceOperationResult { 11 | 12 | private String accountNumber; 13 | private String saldo; 14 | private String incomeSum; 15 | private String outcomeSum; 16 | private String unpaidAmount; 17 | private List entries; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/finance/operations/OperationEntry.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.finance.operations; 2 | 3 | 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | @Data 8 | @Builder 9 | public class OperationEntry { 10 | 11 | private String operationDate; 12 | private String value; 13 | private String title; 14 | private String paymentGateway; 15 | private String paymentAccountDetails; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/marks/JsosMark.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.marks; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | @Getter 10 | @lombok.Builder 11 | @Setter 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @ToString 15 | public class JsosMark { 16 | 17 | private String prowadzacy; 18 | private String kodKursu; 19 | private String nazwaKursu; 20 | private String formaZajec; 21 | private String ZZU; 22 | private String ocena; 23 | private String data; 24 | private String ects; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/marks/JsosSemester.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.marks; 2 | 3 | import java.util.List; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | import lombok.ToString; 11 | @ToString 12 | @Getter 13 | @Setter 14 | @Builder 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class JsosSemester { 18 | 19 | private String semesterName; 20 | private List marks; 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/messages/JsosMessageFull.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.messages; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class JsosMessageFull { 9 | 10 | private String from; 11 | private String to; 12 | private String message; 13 | private int internalId; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/messages/JsosMessageShort.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.messages; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | @Data 8 | @Builder 9 | @JsonIgnoreProperties("detailsLink") 10 | public class JsosMessageShort { 11 | 12 | private String from; 13 | private String subject; 14 | private String date; 15 | private String priority; 16 | private boolean read; 17 | private int internalId; 18 | private String detailsLink; 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/weeks/JsosDay.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.weeks; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import lombok.AllArgsConstructor; 7 | import lombok.Builder; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | import lombok.ToString; 11 | 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @ToString 17 | public class JsosDay { 18 | 19 | private String date; 20 | private List subjects = new ArrayList(); 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/weeks/JsosDaySubject.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.weeks; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.ToString; 8 | 9 | @Data 10 | @Builder 11 | @NoArgsConstructor 12 | @ToString 13 | @AllArgsConstructor 14 | public class JsosDaySubject { 15 | 16 | private String data; 17 | private String nazwaPrzedmiotu; 18 | private String lokalizacja; 19 | private String prowadzacy; 20 | private String kodGrupy; 21 | private String liczbaZapisanych; 22 | private String type; 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/jsos/weeks/JsosWeek.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.jsos.weeks; 2 | 3 | import lombok.*; 4 | 5 | @Data 6 | @Builder 7 | @AllArgsConstructor 8 | @ToString 9 | public class JsosWeek { 10 | 11 | private String weekName; 12 | private JsosDay pn; 13 | private JsosDay wt; 14 | private JsosDay sr; 15 | private JsosDay czw; 16 | private JsosDay pt; 17 | private JsosDay sb; 18 | private JsosDay nd; 19 | 20 | public JsosWeek() { 21 | this.weekName = ""; 22 | this.pn = new JsosDay(); 23 | this.wt = new JsosDay(); 24 | this.sr = new JsosDay(); 25 | this.czw = new JsosDay(); 26 | this.pt = new JsosDay(); 27 | this.sb = new JsosDay(); 28 | this.nd = new JsosDay(); 29 | } 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/prowadzacy/ProwadzacyDay.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.prowadzacy; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | @Builder 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class ProwadzacyDay { 15 | 16 | private String date; 17 | private List lessons; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/prowadzacy/ProwadzacyLesson.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.prowadzacy; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class ProwadzacyLesson { 9 | 10 | private String time; 11 | private String title; 12 | private String location; 13 | private String teacher; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/entity/prowadzacy/ProwadzacyResult.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.entity.prowadzacy; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | @Builder 10 | public class ProwadzacyResult { 11 | 12 | private String title; 13 | private ProwadzacyDay pn; 14 | private ProwadzacyDay wt; 15 | private ProwadzacyDay sr; 16 | private ProwadzacyDay czw; 17 | private ProwadzacyDay pt; 18 | private ProwadzacyDay sb; 19 | private ProwadzacyDay nd; 20 | private String icalLink; 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/http/CORSFilter.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.http; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 6 | 7 | import javax.servlet.*; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.io.IOException; 11 | 12 | @Configuration 13 | @EnableWebMvc 14 | @Slf4j 15 | public class CORSFilter implements Filter { 16 | 17 | @Override 18 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 19 | 20 | if (servletResponse instanceof HttpServletResponse) { 21 | HttpServletResponse response = (HttpServletResponse) servletResponse; 22 | HttpServletRequest request = (HttpServletRequest) servletRequest; 23 | response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); 24 | response.setHeader("Access-Control-Allow-Credentials", "true"); 25 | response.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, HEAD"); 26 | response.setHeader("Access-Control-Max-Age", "3600"); 27 | response.setHeader("Access-Control-Allow-Headers", "*"); 28 | 29 | if ("OPTIONS".equalsIgnoreCase((request.getMethod()))) { 30 | response.setStatus(HttpServletResponse.SC_OK); 31 | } else { 32 | filterChain.doFilter(request, response); 33 | } 34 | log.info("Added CORS headers to response using CORSFilter"); 35 | 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/scrapper/edukacja/EduScrapperServices.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.scrapper.edukacja; 2 | 3 | import dev.wms.pwrapi.dto.edukacja.EduConnection; 4 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 5 | import io.github.bonigarcia.wdm.WebDriverManager; 6 | import okhttp3.*; 7 | import org.jsoup.Jsoup; 8 | import org.jsoup.nodes.Document; 9 | import org.openqa.selenium.By; 10 | import org.openqa.selenium.WebDriver; 11 | import org.openqa.selenium.chrome.ChromeDriver; 12 | import org.openqa.selenium.chrome.ChromeOptions; 13 | 14 | import java.io.IOException; 15 | import java.util.List; 16 | 17 | public class EduScrapperServices { 18 | 19 | /** Selenium login **/ 20 | public static WebDriver login(String login, String password) { 21 | WebDriver driver = null; 22 | 23 | WebDriverManager.chromedriver().setup(); 24 | 25 | ChromeOptions options = new ChromeOptions(); 26 | options.addArguments("start-maximized"); 27 | options.addArguments("enable-automation"); 28 | options.addArguments("--no-sandbox"); 29 | options.addArguments("--disable-infobars"); 30 | options.addArguments("--disable-dev-shm-usage"); 31 | options.addArguments("--disable-browser-side-navigation"); 32 | options.addArguments("--disable-gpu"); 33 | options.addArguments("--headless"); 34 | options.addArguments("--blink-settings=imagesEnabled=false"); 35 | driver = new ChromeDriver(options); 36 | 37 | 38 | driver.get("https://edukacja.pwr.wroc.pl/"); 39 | 40 | driver.findElement(By.name("login")).sendKeys(login); 41 | driver.findElement(By.name("password")).sendKeys(password); 42 | 43 | driver.findElement(By.cssSelector(".BUTTON_ZALOGUJ")).click(); 44 | 45 | 46 | return driver; 47 | } 48 | 49 | //** logins to edukacja.cl using HTML methods. Throws error if something is wrong */ 50 | public static EduConnection fetchHTMLConnectionDetails(String login, String password) throws IOException, LoginException { 51 | 52 | // the object where connection details are stored 53 | EduConnection connectionDetails = new EduConnection(); 54 | 55 | OkHttpClient client = new OkHttpClient(); 56 | 57 | // connects with education website, receives cookies and parses jsessionid 58 | // parsed jsessionid is then stored in connectionDetails DTO 59 | Request request = new Request.Builder() 60 | .url("https://edukacja.pwr.wroc.pl/EdukacjaWeb/studia.do") 61 | .method("GET", null) 62 | .build(); 63 | Response response = client.newCall(request).execute(); 64 | List Cookielist = response.headers().values("Set-Cookie"); 65 | String jsessionid = (Cookielist .get(0).split(";"))[0].replace("JSESSIONID=", ""); 66 | connectionDetails.setJsessionid(jsessionid); 67 | System.out.println(Cookielist); 68 | 69 | // retrieves login page of education as string 70 | String responseBody = response.body().string(); 71 | 72 | // parses string response body with Jsoup parser 73 | Document page = Jsoup.parse(responseBody); 74 | 75 | String webTOKEN = page.select("[name=cl.edu.web.TOKEN]").attr("value"); 76 | connectionDetails.setWebToken(webTOKEN); 77 | 78 | 79 | System.out.println("Web token: " + webTOKEN); 80 | System.out.println(page.html()); 81 | 82 | MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); 83 | RequestBody body = RequestBody.create(mediaType, "cl.edu.web.TOKEN=" + webTOKEN + "&login=" + login + "&password=" + password); 84 | request = new Request.Builder() 85 | .url("https://edukacja.pwr.wroc.pl/EdukacjaWeb/logInUser.do") 86 | .method("POST", body) 87 | .addHeader("Cookie", "JSESSIONID=" + jsessionid) 88 | .build(); 89 | 90 | response = client.newCall(request).execute(); 91 | 92 | if(response.header("Content-Location").contains("logInError.jsp")){ 93 | System.out.println("Throwing login exception"); 94 | throw new LoginException(); 95 | } 96 | 97 | responseBody = response.body().string(); 98 | page = Jsoup.parse(responseBody); 99 | String sessionTOKEN = page.select("[name=clEduWebSESSIONTOKEN]").attr("value"); 100 | 101 | connectionDetails.setSessionToken(sessionTOKEN); 102 | 103 | return connectionDetails; 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/scrapper/eportal/EportalScrapperService.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.scrapper.eportal; 2 | 3 | import java.io.IOException; 4 | 5 | 6 | import org.jsoup.Jsoup; 7 | import org.jsoup.nodes.Document; 8 | 9 | import dev.wms.pwrapi.dto.eportal.userDetails; 10 | import dev.wms.pwrapi.utils.cookies.CookieJarImpl; 11 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 12 | import lombok.Getter; 13 | import okhttp3.CookieJar; 14 | import okhttp3.MediaType; 15 | import okhttp3.OkHttpClient; 16 | import okhttp3.Request; 17 | import okhttp3.RequestBody; 18 | import okhttp3.Response; 19 | 20 | @Getter 21 | public class EportalScrapperService { 22 | 23 | private static OkHttpClient client; 24 | 25 | public static userDetails loginToEportal(String login, String password) throws IOException { 26 | 27 | 28 | CookieJar jar = new CookieJarImpl(); 29 | client = new OkHttpClient.Builder() 30 | .cookieJar(jar) 31 | .build(); 32 | 33 | Request request = new Request.Builder() 34 | .url("https://eportal.pwr.edu.pl/login/index.php?authJSOS=JSOS") 35 | .build(); 36 | 37 | Response response = client.newCall(request).execute(); 38 | 39 | String responseString = response.body().string(); 40 | System.out.println(responseString); 41 | Document doc = Jsoup.parse(responseString); 42 | 43 | String oauthConsumerKey = doc.select("input[name=oauth_consumer_key]").attr("value"); 44 | String oauthToken = doc.select("input[name=oauth_token]").attr("value"); 45 | 46 | MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded"); 47 | RequestBody body = RequestBody.create(mediaType, 48 | "authenticateButton=Zaloguj&ida_hf_0=&oauth_callback_url=https://jsos.pwr.edu.pl/index.php/site/loginAsStudent" 49 | + 50 | "&oauth_consumer_key=" + oauthConsumerKey + 51 | "&oauth_locale=pl" + 52 | "&oauth_request_url=http://oauth.pwr.edu.pl/oauth/authenticate&oauth_symbol=EIS" + 53 | "&oauth_token=" + oauthToken + 54 | "&password=" + password + 55 | "&username=" + login); 56 | 57 | request = new Request.Builder() 58 | .url("https://oauth.pwr.edu.pl/oauth/authenticate?9-1.IFormSubmitListener-authenticateForm" + 59 | "&oauth_token=" + oauthToken + 60 | "&oauth_consumer_key=" + oauthConsumerKey + 61 | "&oauth_locale=pl") 62 | .method("POST", body) 63 | .addHeader("sec-ch-ua", 64 | "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"100\", \"Google Chrome\";v=\"100\"") 65 | .addHeader("sec-ch-ua-mobile", "?0") 66 | .addHeader("sec-ch-ua-platform", "\"Windows\"") 67 | .addHeader("Upgrade-Insecure-Requests", "1") 68 | .addHeader("Content-Type", "application/x-www-form-urlencoded") 69 | .addHeader("User-Agent", 70 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36") 71 | .addHeader("Accept", 72 | "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9") 73 | .addHeader("Sec-Fetch-Site", "same-origin") 74 | .addHeader("Sec-Fetch-Mode", "navigate") 75 | .addHeader("Sec-Fetch-User", "?1") 76 | .addHeader("Sec-Fetch-Dest", "document") 77 | // .addHeader("Cookie", "JSESSIONID=" + jsosConnection.getOauthSessionToken()) 78 | .build(); 79 | 80 | response = client.newCall(request).execute(); 81 | responseString = response.body().string(); 82 | if(responseString.contains("Niepowodzenie logowania. Niepoprawna nazwa użytkownika lub hasło.")) throw new LoginException(); 83 | 84 | doc = Jsoup.parse(responseString); 85 | 86 | userDetails details = new userDetails().builder() 87 | .username("Feautre not supported.") 88 | .userID(0) 89 | .build(); 90 | 91 | return details; 92 | } 93 | 94 | public static OkHttpClient getClient() { 95 | return client; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/edukacja/EduService.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.edukacja; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.entity.edukacja.Subject; 5 | 6 | import java.util.List; 7 | 8 | public interface EduService { 9 | 10 | List doFetchSubjects(String login, String password) throws JsonProcessingException; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/edukacja/EduServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.edukacja; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.dao.edukacja.EduSubjectDAO; 5 | import dev.wms.pwrapi.entity.edukacja.Subject; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.List; 10 | 11 | @Service 12 | public class EduServiceImpl implements EduService { 13 | 14 | private EduSubjectDAO eduSubjectDAO; 15 | 16 | @Autowired 17 | public EduServiceImpl(EduSubjectDAO eduSubjectDAO){ 18 | this.eduSubjectDAO = eduSubjectDAO; 19 | } 20 | 21 | @Override 22 | public List doFetchSubjects(String login, String password) throws JsonProcessingException { 23 | return eduSubjectDAO.doFetchSubjects(login, password); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/eportal/EportalService.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.eportal; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.entity.eportal.MarkSummary; 5 | import dev.wms.pwrapi.entity.eportal.calendar.CalendarMonth; 6 | import dev.wms.pwrapi.dto.eportal.sections.EportalSection; 7 | import dev.wms.pwrapi.utils.eportal.exceptions.WrongCourseIdException; 8 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 9 | 10 | import java.io.IOException; 11 | import java.util.List; 12 | 13 | public interface EportalService { 14 | String getEportalData(String login, String password) throws JsonProcessingException, IOException, LoginException; 15 | 16 | String getEportalKursy(String login, String password) throws JsonProcessingException, IOException, LoginException; 17 | 18 | List getEportalSekcje(String login, String password, int id) throws JsonProcessingException, IOException, LoginException, WrongCourseIdException; 19 | 20 | List getEportalOceny(String login, String password, int id) throws JsonProcessingException; 21 | 22 | CalendarMonth getEportalKalendarzOffset(String login, String password, int offset) throws IOException; 23 | 24 | String getEportalKalendarzIcsLink(String login, String password) throws IOException; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/eportal/EportalServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.eportal; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.dao.eportal.EportalCalendarDAO; 5 | import dev.wms.pwrapi.dao.eportal.EportalDAO; 6 | import dev.wms.pwrapi.entity.eportal.MarkSummary; 7 | import dev.wms.pwrapi.entity.eportal.calendar.CalendarMonth; 8 | import dev.wms.pwrapi.dto.eportal.sections.EportalSection; 9 | import dev.wms.pwrapi.utils.eportal.exceptions.WrongCourseIdException; 10 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | 14 | import java.io.IOException; 15 | import java.util.List; 16 | 17 | 18 | @Service 19 | public class EportalServiceImpl implements EportalService { 20 | 21 | private EportalDAO generalDAO; 22 | private EportalCalendarDAO calendarDAO; 23 | 24 | @Autowired 25 | public EportalServiceImpl(EportalDAO generalDAO, EportalCalendarDAO calendarDAO){ 26 | this.generalDAO = generalDAO; 27 | this.calendarDAO = calendarDAO; 28 | } 29 | 30 | @Override 31 | public String getEportalData(String login, String password) throws JsonProcessingException, IOException, LoginException { 32 | return generalDAO.login(login, password); 33 | } 34 | 35 | @Override 36 | public String getEportalKursy(String login, String password) throws JsonProcessingException, IOException, LoginException { 37 | return generalDAO.getEportalKursy(login, password); 38 | } 39 | 40 | @Override 41 | public List getEportalSekcje(String login, String password, int id) throws JsonProcessingException, IOException, LoginException, WrongCourseIdException { 42 | return generalDAO.getEportalSekcje(login, password, id); 43 | } 44 | 45 | 46 | @Override 47 | public List getEportalOceny(String login, String password, int id) throws JsonProcessingException { 48 | return generalDAO.getEportalOceny(login, password, id); 49 | } 50 | 51 | 52 | @Override 53 | public CalendarMonth getEportalKalendarzOffset(String login, String password, int offset) throws IOException { 54 | return calendarDAO.getEventsWithOffset(login, password, offset); 55 | } 56 | 57 | @Override 58 | public String getEportalKalendarzIcsLink(String login, String password) throws IOException { 59 | return calendarDAO.getIcsCalendarUrl(login, password); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/forum/ForumService.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.forum; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.entity.forum.Review; 5 | import dev.wms.pwrapi.entity.forum.Teacher; 6 | import dev.wms.pwrapi.utils.forum.dto.DatabaseMetadataDTO; 7 | 8 | import java.util.List; 9 | 10 | public interface ForumService { 11 | DatabaseMetadataDTO getDatabaseMetadata() throws JsonProcessingException; 12 | DatabaseMetadataDTO getTotalReviews() throws JsonProcessingException; 13 | Review getReviewById(int id) throws JsonProcessingException; 14 | DatabaseMetadataDTO getTotalTeachers() throws JsonProcessingException; 15 | Teacher fetchLimitedTeacherReviewsById(int teacherId, int limit) throws JsonProcessingException; 16 | Teacher fetchLimitedTeacherReviewsByFullName(String firstName, String lastName, int limit) throws JsonProcessingException; 17 | List getTeachersByCategory(String category) throws JsonProcessingException; 18 | List getBestTeachersRankedByCategory(String category) throws JsonProcessingException; 19 | 20 | List getWorstTeachersRankedByCategory(String category) throws JsonProcessingException; 21 | 22 | List getBestRankedTeachersByCategoryLimited(String category, int limit) throws JsonProcessingException; 23 | List getWorstRankedTeachersByCategoryLimited(String category, int limit) throws JsonProcessingException; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/forum/ForumServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.forum; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.dao.forum.ForumDAO; 5 | import dev.wms.pwrapi.dao.forum.ForumDAOImpl; 6 | import dev.wms.pwrapi.entity.forum.Review; 7 | import dev.wms.pwrapi.entity.forum.Teacher; 8 | import dev.wms.pwrapi.utils.forum.dto.DatabaseMetadataDTO; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import java.util.List; 12 | 13 | @Service 14 | public class ForumServiceImpl implements ForumService { 15 | 16 | private final ForumDAO forumDAO; 17 | 18 | @Autowired 19 | public ForumServiceImpl(ForumDAOImpl forumDAOImpl){ 20 | this.forumDAO = forumDAOImpl; 21 | } 22 | 23 | @Override 24 | public DatabaseMetadataDTO getDatabaseMetadata() { 25 | int totalTeachers = forumDAO.getNumberOfTeachers(); 26 | int totalReviews = forumDAO.getNumberOfReviews(); 27 | String latestRefreshDate = forumDAO.getLastRefreshDate(); 28 | DatabaseMetadataDTO databaseMetadataDTO = new DatabaseMetadataDTO(totalTeachers, totalReviews, latestRefreshDate); 29 | return databaseMetadataDTO; 30 | } 31 | 32 | @Override 33 | public DatabaseMetadataDTO getTotalReviews() { 34 | int totalReviews = forumDAO.getNumberOfReviews(); 35 | DatabaseMetadataDTO databaseMetadataDTO = new DatabaseMetadataDTO(); 36 | databaseMetadataDTO.setTotalReviews(totalReviews); 37 | return databaseMetadataDTO; 38 | } 39 | 40 | @Override 41 | public Review getReviewById(int id) { 42 | Review review = forumDAO.findReviewById(id); 43 | return review; 44 | } 45 | 46 | @Override 47 | public DatabaseMetadataDTO getTotalTeachers() { 48 | int totalTeachers = forumDAO.getNumberOfTeachers(); 49 | DatabaseMetadataDTO databaseMetadataDTO = new DatabaseMetadataDTO(); 50 | databaseMetadataDTO.setTotalTeachers(totalTeachers); 51 | return databaseMetadataDTO; 52 | } 53 | 54 | @Override 55 | public Teacher fetchLimitedTeacherReviewsById(int teacherId, int limit) { 56 | if(limit == -1) { 57 | Teacher teacher = forumDAO.fetchTeacherByIdWithReviews(teacherId); 58 | return teacher; 59 | } 60 | Teacher teacher = forumDAO.fetchTeacherByIdWithLimitedReviews(teacherId, limit); 61 | return teacher; 62 | } 63 | 64 | @Override 65 | public Teacher fetchLimitedTeacherReviewsByFullName(String firstName, String lastName, int limit) { 66 | if(limit == -1){ 67 | Teacher teacher = forumDAO.fetchTeacherByFullNameWithReviews(firstName, lastName); 68 | return teacher; 69 | } 70 | Teacher teacher = forumDAO.fetchTeacherByFullNameWithLimitedReviews(firstName, lastName, limit); 71 | return teacher; 72 | } 73 | 74 | @Override 75 | public List getTeachersByCategory(String category) { 76 | return forumDAO.getTeachersByCategory(category); 77 | } 78 | 79 | @Override 80 | public List getBestTeachersRankedByCategory(String category) { 81 | return forumDAO.getTeachersRankedByCategory(category, false); 82 | } 83 | 84 | @Override 85 | public List getWorstTeachersRankedByCategory(String category) { 86 | List teachers = forumDAO.getTeachersRankedByCategory(category, false); 87 | return teachers; 88 | } 89 | 90 | @Override 91 | public List getBestRankedTeachersByCategoryLimited(String category, int limit) { 92 | return forumDAO.fetchWorstOrBestTeachersByCategoryWithReviewsLimited(category, limit, 3, true); 93 | } 94 | 95 | @Override 96 | public List getWorstRankedTeachersByCategoryLimited(String category, int limit) { 97 | return forumDAO.fetchWorstOrBestTeachersByCategoryWithReviewsLimited(category, limit, 3, false); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/jsos/JsosService.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.jsos; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.entity.jsos.JsosLesson; 5 | import dev.wms.pwrapi.entity.jsos.JsosStudentData; 6 | import dev.wms.pwrapi.entity.jsos.finance.FinanceResult; 7 | import dev.wms.pwrapi.entity.jsos.finance.operations.FinanceOperationResult; 8 | import dev.wms.pwrapi.entity.jsos.marks.JsosSemester; 9 | import dev.wms.pwrapi.entity.jsos.messages.JsosMessageFull; 10 | import dev.wms.pwrapi.entity.jsos.messages.JsosMessageShort; 11 | import dev.wms.pwrapi.entity.jsos.weeks.JsosDay; 12 | import dev.wms.pwrapi.entity.jsos.weeks.JsosWeek; 13 | import dev.wms.pwrapi.dto.jsos.JsosConnection; 14 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 15 | 16 | import java.io.IOException; 17 | import java.util.List; 18 | 19 | public interface JsosService { 20 | JsosWeek getOffsetLessons(String login, String password, int offset) throws IOException, LoginException; 21 | 22 | JsosDay getTodaysLessions(String login, String password) throws IOException, LoginException, dev.wms.pwrapi.utils.jsos.exceptions.NoTodayClassException; 23 | 24 | JsosDay getTomorrowLessons(String login, String password) throws IOException, LoginException; 25 | 26 | JsosWeek getThisWeekLessons(String login, String password) throws IOException, LoginException; 27 | 28 | JsosWeek getNextWeekLessons(String login, String password) throws IOException, LoginException; 29 | 30 | List getAllStudentsLessons(String login, String password) throws IOException, LoginException; 31 | 32 | List getStudentMarks(String login, String password) 33 | throws JsonProcessingException, IOException, LoginException; 34 | 35 | JsosConnection login(String login, String password) throws LoginException; 36 | 37 | JsosStudentData getStudentData(String login, String password) throws LoginException; 38 | FinanceResult getStudentFinanse(String login, String password) throws IOException; 39 | FinanceOperationResult getStudentFinanceOperations(String login, String password) throws IOException; 40 | List getStudentMessagesList(String login, String password, int page) throws IOException; 41 | List getStudentMessage(String login, String password, int page, Integer... ids) throws IOException; 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/jsos/JsosServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.jsos; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | 8 | import dev.wms.pwrapi.dao.jsos.JsosDataDAO; 9 | import dev.wms.pwrapi.dao.jsos.JsosGeneralDAO; 10 | import dev.wms.pwrapi.dao.jsos.JsosLessonsDAO; 11 | import dev.wms.pwrapi.entity.jsos.JsosLesson; 12 | import dev.wms.pwrapi.entity.jsos.JsosStudentData; 13 | import dev.wms.pwrapi.entity.jsos.finance.FinanceResult; 14 | import dev.wms.pwrapi.entity.jsos.finance.operations.FinanceOperationResult; 15 | import dev.wms.pwrapi.entity.jsos.marks.JsosSemester; 16 | import dev.wms.pwrapi.entity.jsos.messages.JsosMessageFull; 17 | import dev.wms.pwrapi.entity.jsos.messages.JsosMessageShort; 18 | import dev.wms.pwrapi.entity.jsos.weeks.JsosDay; 19 | import dev.wms.pwrapi.entity.jsos.weeks.JsosWeek; 20 | import dev.wms.pwrapi.dto.jsos.JsosConnection; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | 24 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 25 | 26 | @Service 27 | public class JsosServiceImpl implements JsosService { 28 | 29 | private JsosGeneralDAO generalDAO; 30 | private JsosDataDAO dataDAO; 31 | private JsosLessonsDAO lessonsDAO; 32 | 33 | @Autowired 34 | public JsosServiceImpl(JsosGeneralDAO generalDAO, JsosDataDAO dataDAO, JsosLessonsDAO lessonsDAO) { 35 | this.generalDAO = generalDAO; 36 | this.dataDAO = dataDAO; 37 | this.lessonsDAO = lessonsDAO; 38 | } 39 | 40 | @Override 41 | public JsosWeek getOffsetLessons(String login, String password, int offset) throws IOException, LoginException{ 42 | return lessonsDAO.getOffsetWeekLessons(login, password, offset); 43 | } 44 | 45 | @Override 46 | public JsosDay getTodaysLessions(String login, String password) throws IOException, LoginException, dev.wms.pwrapi.utils.jsos.exceptions.NoTodayClassException{ 47 | return lessonsDAO.getTodaysLessons(login, password); 48 | } 49 | 50 | @Override 51 | public JsosDay getTomorrowLessons(String login, String password) throws IOException, LoginException{ 52 | return lessonsDAO.getTomorrowLessons(login, password); 53 | } 54 | 55 | @Override 56 | public JsosWeek getThisWeekLessons(String login, String password) throws IOException, LoginException{ 57 | return lessonsDAO.getThisWeekLessons(login, password); 58 | } 59 | 60 | @Override 61 | public JsosWeek getNextWeekLessons(String login, String password) throws IOException, LoginException{ 62 | return lessonsDAO.getNextWeekLessons(login, password); 63 | } 64 | 65 | @Override 66 | public List getAllStudentsLessons(String login, String password) throws IOException, LoginException{ 67 | return lessonsDAO.getAllLessons(login, password); 68 | } 69 | 70 | @Override 71 | public List getStudentMarks(String login, String password) 72 | throws JsonProcessingException, IOException, LoginException { 73 | 74 | return dataDAO.getStudentMarks(login, password); 75 | 76 | } 77 | 78 | @Override 79 | public JsosConnection login(String login, String password) throws LoginException { 80 | 81 | JsosConnection result; 82 | 83 | try { 84 | result = generalDAO.login(login, password); 85 | } catch (IOException e) { 86 | throw new RuntimeException(e); 87 | } 88 | 89 | return result; 90 | } 91 | 92 | @Override 93 | public JsosStudentData getStudentData(String login, String password) throws LoginException { 94 | 95 | JsosStudentData result = null; 96 | 97 | try { 98 | result = dataDAO.getStudentData(login, password); 99 | } catch (IOException i) { 100 | i.printStackTrace(); 101 | } 102 | 103 | return result; 104 | 105 | } 106 | 107 | @Override 108 | public FinanceResult getStudentFinanse(String login, String password) throws IOException { 109 | return dataDAO.getStudentFinance(login, password); 110 | } 111 | 112 | @Override 113 | public FinanceOperationResult getStudentFinanceOperations(String login, String password) throws IOException { 114 | return dataDAO.getStudentFinanceOperations(login, password); 115 | } 116 | 117 | @Override 118 | public List getStudentMessagesList(String login, String password, int page) throws IOException { 119 | return dataDAO.getStudentMessages(login, password, page); 120 | } 121 | 122 | @Override 123 | public List getStudentMessage(String login, String password, int page, Integer... ids) throws IOException { 124 | return dataDAO.getStudentMessage(login, password, page, ids); 125 | } 126 | 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/news/NewsService.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.news; 2 | 3 | import dev.wms.pwrapi.dao.news.NewsDAO; 4 | import dev.wms.pwrapi.dto.news.Channel; 5 | import dev.wms.pwrapi.dto.news.FacultyType; 6 | import lombok.AllArgsConstructor; 7 | import org.springframework.cache.annotation.Cacheable; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | @AllArgsConstructor 12 | public class NewsService { 13 | 14 | private NewsDAO newsDAO; 15 | 16 | @Cacheable("pwr-news") 17 | public Channel fetchGeneralNews() { 18 | System.out.println("FETCHING NEW NEWSES"); 19 | return newsDAO.parsePwrRSS("https://pwr.edu.pl/rss/pl/24.xml"); 20 | } 21 | 22 | @Cacheable("pwr-news") 23 | public Channel fetchNewsForFaculty(FacultyType faculty) { 24 | System.out.println("FETCHING NEW NEWSES"); 25 | return newsDAO.getFacultyNews(faculty); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/parking/ParkingProxy.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.parking; 2 | 3 | import dev.wms.pwrapi.dao.parking.ParkingDAO; 4 | import dev.wms.pwrapi.dto.parking.Parking; 5 | import dev.wms.pwrapi.dto.parking.ParkingWithHistory; 6 | import dev.wms.pwrapi.utils.parking.ParkingDateUtils; 7 | import org.springframework.beans.factory.annotation.Qualifier; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.io.IOException; 11 | import java.time.LocalDateTime; 12 | import java.time.format.DateTimeFormatter; 13 | import java.util.List; 14 | 15 | /** 16 | * In order to reduce stress on university servers, we use proxy design pattern so 17 | * server is called if we requested data minimum one minute before 18 | */ 19 | @Component 20 | public class ParkingProxy { 21 | 22 | private final ParkingDAO iParkingDAO; 23 | private final ParkingDAO skdParkingDAO; 24 | private List parkingState; 25 | private List parkingWithHistoryState; 26 | 27 | public ParkingProxy(@Qualifier("IParkingDAO") ParkingDAO iParkingDAO, @Qualifier("SKDParkingDAO") ParkingDAO skdParkingDAO) { 28 | this.iParkingDAO = iParkingDAO; 29 | this.skdParkingDAO = skdParkingDAO; 30 | } 31 | 32 | public List getParkingState() throws IOException { 33 | if(parkingStateQualifies(parkingState)){ 34 | parkingState = getProcessedParkingInfo(); 35 | } 36 | return parkingState; 37 | } 38 | 39 | public List getParkingWithHistory() throws IOException { 40 | if(parkingStateWithHistoryQualifiesForUpdate(parkingWithHistoryState)){ 41 | parkingWithHistoryState = getRawParkingInfo(); 42 | 43 | } 44 | return parkingWithHistoryState; 45 | } 46 | 47 | private boolean parkingStateQualifies(List parkingState){ 48 | return parkingState == null || parkingState.isEmpty() || parseUpdateTime(parkingState.get(0).getLastUpdate()) 49 | .isBefore(ParkingDateUtils.getDateTimeInPoland().minusMinutes(1)); 50 | } 51 | 52 | private boolean parkingStateWithHistoryQualifiesForUpdate(List parkingWithHistoryState){ 53 | return parkingWithHistoryState == null || parkingWithHistoryState.isEmpty() || parseUpdateTime(parkingWithHistoryState.get(0).getLastUpdate()).isBefore( 54 | ParkingDateUtils.getDateTimeInPoland().minusMinutes(5) 55 | ); 56 | } 57 | 58 | private LocalDateTime parseUpdateTime(String lastUpdate){ 59 | return LocalDateTime.parse(lastUpdate, DateTimeFormatter.ISO_LOCAL_DATE_TIME); 60 | } 61 | 62 | private List getProcessedParkingInfo(){ 63 | try{ 64 | return iParkingDAO.getProcessedParkingInfo(); 65 | } catch (Throwable t) { 66 | return getSkdProcessedParkingInfo(); 67 | } 68 | } 69 | 70 | private List getRawParkingInfo(){ 71 | try{ 72 | return iParkingDAO.getRawParkingData(); 73 | } catch (Throwable t){ 74 | return getSkdRawParkingInfo(); 75 | } 76 | } 77 | 78 | private List getSkdRawParkingInfo(){ 79 | try { 80 | return skdParkingDAO.getRawParkingData(); 81 | } catch (IOException e) { 82 | throw new RuntimeException(e); 83 | } 84 | } 85 | 86 | private List getSkdProcessedParkingInfo(){ 87 | try { 88 | return skdParkingDAO.getProcessedParkingInfo(); 89 | } catch (IOException e) { 90 | throw new RuntimeException(e); 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/parking/ParkingService.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.parking; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.dto.parking.Parking; 5 | import dev.wms.pwrapi.dto.parking.ParkingWithHistory; 6 | 7 | import java.io.IOException; 8 | import java.util.List; 9 | 10 | public interface ParkingService { 11 | 12 | List getParkingData() throws JsonProcessingException, IOException; 13 | 14 | List getRawParkingData() throws IOException; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/parking/ParkingServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.parking; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | 8 | import dev.wms.pwrapi.dto.parking.Parking; 9 | import dev.wms.pwrapi.dto.parking.ParkingWithHistory; 10 | import lombok.AllArgsConstructor; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | 14 | import dev.wms.pwrapi.dao.parking.ParkingDAO; 15 | 16 | @Service 17 | @AllArgsConstructor 18 | public class ParkingServiceImpl implements ParkingService { 19 | 20 | private ParkingProxy parkingProxy; 21 | 22 | @Override 23 | public List getParkingData() throws JsonProcessingException, IOException{ 24 | return parkingProxy.getParkingState(); 25 | } 26 | 27 | @Override 28 | public List getRawParkingData() throws IOException{ 29 | return parkingProxy.getParkingWithHistory(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/prowadzacy/ProwadzacyService.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.prowadzacy; 2 | 3 | import dev.wms.pwrapi.entity.prowadzacy.ProwadzacyResult; 4 | 5 | public interface ProwadzacyService { 6 | String getWebsiteStatus(); 7 | 8 | ProwadzacyResult getForTeacherQuery(String query, int offset); 9 | 10 | ProwadzacyResult getForRoomQuery(String building, String query, Integer offset); 11 | 12 | ProwadzacyResult getForSubjectQuery(String query, Integer offset); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/service/prowadzacy/ProwadzacyServiceImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.prowadzacy; 2 | 3 | import dev.wms.pwrapi.dao.prowadzacy.ProwadzacyDAO; 4 | import dev.wms.pwrapi.entity.prowadzacy.ProwadzacyResult; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class ProwadzacyServiceImpl implements ProwadzacyService { 10 | 11 | private ProwadzacyDAO prowadzacyDAO; 12 | 13 | @Autowired 14 | public ProwadzacyServiceImpl(ProwadzacyDAO prowadzacyDAO){ 15 | this.prowadzacyDAO = prowadzacyDAO; 16 | } 17 | 18 | @Override 19 | public String getWebsiteStatus(){ 20 | return prowadzacyDAO.connectToWebsite(); 21 | } 22 | 23 | @Override 24 | public ProwadzacyResult getForTeacherQuery(String query, int offset){ 25 | return prowadzacyDAO.getPlanForTeacherQuery(query, offset); 26 | } 27 | 28 | @Override 29 | public ProwadzacyResult getForRoomQuery(String building, String query, Integer offset){ 30 | return prowadzacyDAO.getPlanForRoomQuery(building, query, offset); 31 | } 32 | 33 | @Override 34 | public ProwadzacyResult getForSubjectQuery(String query, Integer offset){ 35 | return prowadzacyDAO.getPlanForSubjectQuery(query, offset); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/config/CachingConfig.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.config; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.cache.annotation.CacheEvict; 8 | import org.springframework.cache.annotation.EnableCaching; 9 | import org.springframework.cache.concurrent.ConcurrentMapCacheManager; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.core.env.ConfigurableEnvironment; 13 | import org.springframework.scheduling.annotation.EnableScheduling; 14 | import org.springframework.scheduling.annotation.Scheduled; 15 | 16 | import javax.annotation.PostConstruct; 17 | import java.util.List; 18 | 19 | @Configuration 20 | @EnableCaching 21 | @EnableScheduling 22 | @Slf4j 23 | public class CachingConfig implements CacheManagerCustomizer { 24 | 25 | @Override 26 | public void customize(ConcurrentMapCacheManager cacheManager) { 27 | cacheManager.setCacheNames(List.of("pwr-news")); 28 | } 29 | 30 | @CacheEvict(allEntries = true, cacheNames = "pwr-news") 31 | @Scheduled(fixedDelayString = "${pwr-api.news.cacheTTL}") 32 | public void reportCacheEvict(){ 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/config/DeserializationConfig.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; 8 | import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 10 | 11 | @Configuration 12 | public class DeserializationConfig { 13 | 14 | @Bean 15 | Jackson2ObjectMapperBuilder getDefaultDeserializer(){ 16 | return Jackson2ObjectMapperBuilder.json(); 17 | } 18 | 19 | @Bean 20 | public WebMvcConfigurer customWebMvcConfigurer(){ 21 | return new WebMvcConfigurer() { 22 | @Override 23 | public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 24 | configurer.defaultContentType(MediaType.APPLICATION_JSON); 25 | } 26 | }; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/config/RequestLoggingConfig.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.filter.CommonsRequestLoggingFilter; 6 | 7 | @Configuration 8 | public class RequestLoggingConfig { 9 | @Bean 10 | public CommonsRequestLoggingFilter logFilter() { 11 | return new CommonsRequestLoggingFilter(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/cookies/CookieJarImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.cookies; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | 7 | import lombok.Getter; 8 | import okhttp3.Cookie; 9 | import okhttp3.CookieJar; 10 | import okhttp3.HttpUrl; 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | @Getter 14 | /** 15 | * This custom implementation of OkHttp's CookieJar provides us with quick switching cookies feature. 16 | * 17 | * For example, if user is logging in and his session cookie is changed, OkHttp will automatically swap 18 | * new cookie with the old one, making OAuth, or JWT authentication smoother. 19 | */ 20 | public class CookieJarImpl implements CookieJar{ 21 | 22 | private final HashMap> cookieStore = new HashMap<>(); 23 | 24 | @Override 25 | public void saveFromResponse(HttpUrl url, @NotNull List cookies) { 26 | 27 | if(cookieStore.get(url.host()) != null && cookies != null){ 28 | System.out.println("Trying to add cookies " + cookies); 29 | for(Cookie c : cookies){ 30 | 31 | for(int i = 0; i < cookieStore.get(url.host()).size(); i++){ 32 | Cookie k = cookieStore.get(url.host()).get(i); 33 | if(c.name().equals(k.name())){ 34 | cookieStore.get(url.host()).remove(k); 35 | i--; 36 | } 37 | 38 | System.out.println("Removed duplicate cookie " + c.name()); 39 | } 40 | 41 | cookieStore.get(url.host()).add(c); 42 | 43 | } 44 | } else { 45 | cookieStore.put(url.host(), new ArrayList<>(cookies)); 46 | } 47 | 48 | } 49 | 50 | @Override 51 | public List loadForRequest(HttpUrl url) { 52 | List cookies = cookieStore.get(url.host()); 53 | System.out.println("Using cookies: " + cookies); 54 | return cookies != null ? cookies : new ArrayList<>(); 55 | } 56 | 57 | 58 | } -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/edukacja/advice/EdukacjaAPIAdvice.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.edukacja.advice; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.utils.edukacja.exceptions.EnrollmentAccessDeniedException; 5 | import dev.wms.pwrapi.utils.generalExceptionHandling.ResponseMessageHandler; 6 | import org.springframework.http.HttpHeaders; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | import org.springframework.web.bind.annotation.ResponseStatus; 13 | import org.springframework.web.bind.annotation.RestControllerAdvice; 14 | 15 | @RestControllerAdvice 16 | public class EdukacjaAPIAdvice { 17 | 18 | private static final HttpHeaders headers; 19 | 20 | static { 21 | headers = new HttpHeaders(); 22 | headers.setContentType(MediaType.APPLICATION_JSON); 23 | } 24 | 25 | @ExceptionHandler(EnrollmentAccessDeniedException.class) 26 | public ResponseEntity enrollmentAccessDeniedHandler(EnrollmentAccessDeniedException ex) throws JsonProcessingException { 27 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 28 | return new ResponseEntity<>(response, headers, HttpStatus.FORBIDDEN); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/edukacja/exceptions/EnrollmentAccessDeniedException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.edukacja.exceptions; 2 | 3 | public class EnrollmentAccessDeniedException extends RuntimeException { 4 | 5 | public EnrollmentAccessDeniedException(){ 6 | super("Prawo do zapisów w aktualnym cyklu zapisowym nie zostało przyznane, odczyt grup niemożliwy."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/eportal/EportalGeneralUtils.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.eportal; 2 | 3 | import dev.wms.pwrapi.dto.eportal.sections.EportalElementType; 4 | 5 | public class EportalGeneralUtils { 6 | 7 | /** 8 | * Converts ePortal's URL to EportalElementType enum for nice output formatting 9 | * @param url ePortal url for resource 10 | * @return EportalElementTypeEnum corresponding to known types, INNE for unknown types 11 | */ 12 | public static EportalElementType determineElementTypeFromUrl(String url) { 13 | 14 | if (url.contains("assign")) 15 | return EportalElementType.ZADANIE; 16 | if (url.contains("pdf")) 17 | return EportalElementType.PDF; 18 | if (url.contains("powerpoint")) 19 | return EportalElementType.PREZENTACJA; 20 | if (url.contains("core")) 21 | return EportalElementType.PLIK; 22 | if (url.contains("url")) 23 | return EportalElementType.LINK; 24 | if (url.contains("page")) 25 | return EportalElementType.LINK; 26 | if (url.contains("archive")) 27 | return EportalElementType.ARCHIWUM; 28 | if (url.contains("reservation")) 29 | return EportalElementType.REZERWACJA; 30 | if (url.contains("quiz")) 31 | return EportalElementType.QUIZ; 32 | 33 | return EportalElementType.INNE; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/eportal/advice/EportalAPIAdvice.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.eportal.advice; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.dto.ExceptionMessagingDTO; 5 | import dev.wms.pwrapi.utils.eportal.exceptions.WrongCourseIdException; 6 | import dev.wms.pwrapi.utils.generalExceptionHandling.ResponseMessageHandler; 7 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 8 | import org.springframework.http.HttpHeaders; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.ExceptionHandler; 13 | import org.springframework.web.bind.annotation.RestControllerAdvice; 14 | 15 | @RestControllerAdvice 16 | public class EportalAPIAdvice { 17 | 18 | private static final HttpHeaders headers; 19 | 20 | static{ 21 | headers = new HttpHeaders(); 22 | headers.setContentType(MediaType.APPLICATION_JSON); 23 | } 24 | 25 | @ExceptionHandler(LoginException.class) 26 | public ResponseEntity handleException(LoginException e) throws JsonProcessingException { 27 | String response = ResponseMessageHandler.createResponseMessageJSON("Błędny login, lub hasło."); 28 | return new ResponseEntity<>(response, headers, HttpStatus.UNAUTHORIZED); 29 | } 30 | 31 | @ExceptionHandler(WrongCourseIdException.class) 32 | public ResponseEntity handleException(WrongCourseIdException e) throws JsonProcessingException { 33 | String response = ResponseMessageHandler.createResponseMessageJSON("Nie posiadasz uprawnień do tego kursu."); 34 | return new ResponseEntity<>(response, headers, HttpStatus.UNAUTHORIZED); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/eportal/exceptions/WrongCourseIdException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.eportal.exceptions; 2 | 3 | public class WrongCourseIdException extends RuntimeException{ 4 | 5 | 6 | public WrongCourseIdException(){ 7 | super("You don't have access to course with given ID."); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/advice/ForumAPIAdvice.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.advice; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.utils.forum.exceptions.*; 5 | import dev.wms.pwrapi.utils.generalExceptionHandling.ResponseMessageHandler; 6 | import org.springframework.http.HttpHeaders; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.RestControllerAdvice; 12 | 13 | @RestControllerAdvice 14 | public class ForumAPIAdvice { 15 | 16 | private static final HttpHeaders headers; 17 | 18 | static{ 19 | headers = new HttpHeaders(); 20 | headers.setContentType(MediaType.APPLICATION_JSON); 21 | } 22 | 23 | @ExceptionHandler(ReviewNotFoundException.class) 24 | public ResponseEntity reviewNotFoundExceptionHandler(ReviewNotFoundException ex) throws JsonProcessingException { 25 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 26 | return new ResponseEntity<>(response, headers, HttpStatus.NOT_FOUND); 27 | } 28 | 29 | @ExceptionHandler(TeacherNotFoundByIdException.class) 30 | public ResponseEntity teacherNotFoundExceptionHandler(TeacherNotFoundByIdException ex) throws JsonProcessingException { 31 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 32 | return new ResponseEntity<>(response, headers, HttpStatus.NOT_FOUND); 33 | } 34 | 35 | @ExceptionHandler(TeacherNotFoundByFullNameException.class) 36 | public ResponseEntity teacherNotFoundByFullNameExceptionHandler(TeacherNotFoundByFullNameException ex) throws JsonProcessingException { 37 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 38 | return new ResponseEntity<>(response, headers, HttpStatus.NOT_FOUND); 39 | } 40 | 41 | @ExceptionHandler(InvalidLimitException.class) 42 | public ResponseEntity invalidLimitExceptionHandler(InvalidLimitException ex) throws JsonProcessingException { 43 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 44 | return new ResponseEntity<>(response, headers, HttpStatus.BAD_REQUEST); 45 | } 46 | 47 | @ExceptionHandler(CategoryMembersNotFoundException.class) 48 | public ResponseEntity categoryMembersNotFoundExceptionHandled(CategoryMembersNotFoundException ex) throws JsonProcessingException { 49 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 50 | return new ResponseEntity<>(response, headers, HttpStatus.BAD_REQUEST); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/config/SpringJdbcConfig.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.ComponentScan; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.jdbc.datasource.DriverManagerDataSource; 8 | 9 | import javax.sql.DataSource; 10 | 11 | @Configuration 12 | @ComponentScan("dev.wms.pwrapi") 13 | public class SpringJdbcConfig { 14 | 15 | @Bean 16 | public DataSource mySqlDataSource(){ 17 | DriverManagerDataSource dataSource = new DriverManagerDataSource(); 18 | dataSource.setUrl(System.getenv("URL")); 19 | dataSource.setUsername(System.getenv("login")); 20 | dataSource.setPassword(System.getenv("password")); 21 | return dataSource; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/dto/DatabaseMetadataDTO.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @JsonInclude(JsonInclude.Include.NON_NULL) 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class DatabaseMetadataDTO { 13 | private Integer totalTeachers; 14 | private Integer totalReviews; 15 | private String latestRefresh; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/exceptions/CategoryMembersNotFoundException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.exceptions; 2 | 3 | public class CategoryMembersNotFoundException extends RuntimeException { 4 | public CategoryMembersNotFoundException(String category){ 5 | super("Nie znaleziono prowadzących w kategorii: " + category + 6 | ". Lista dostępnych kategorii [matematycy, fizycy, informatycy, chemicy, elektronicy, jezykowcy, sportowcy, humanisci, inni]."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/exceptions/InvalidLimitException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.exceptions; 2 | 3 | public class InvalidLimitException extends RuntimeException { 4 | public InvalidLimitException(int limit){ 5 | super("Nieprawidłowy limit: " + limit + ". Ograniczenia limitu: -1 (pobierz wszystkie) <= limit."); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/exceptions/ReviewNotFoundException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.exceptions; 2 | 3 | public class ReviewNotFoundException extends RuntimeException { 4 | 5 | public ReviewNotFoundException(int reviewId){ 6 | super("Opinia o id: " + reviewId + " nie istnieje."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/exceptions/TeacherNotFoundByFullNameException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.exceptions; 2 | 3 | public class TeacherNotFoundByFullNameException extends RuntimeException { 4 | public TeacherNotFoundByFullNameException(String firstName, String lastName){ 5 | super("Prowadzący o imieniu: " + firstName + " " + lastName + " nie istnieje."); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/exceptions/TeacherNotFoundByIdException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.exceptions; 2 | 3 | public class TeacherNotFoundByIdException extends RuntimeException { 4 | public TeacherNotFoundByIdException(int teacherId){ 5 | super("Prowadzący o id: " + teacherId + " nie istnieje."); 6 | } 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/rowMappers/ReviewRowMapper.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.rowMappers; 2 | 3 | import dev.wms.pwrapi.entity.forum.Review; 4 | import org.springframework.jdbc.core.RowMapper; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | 10 | @Component 11 | public class ReviewRowMapper implements RowMapper { 12 | 13 | @Override 14 | public Review mapRow(ResultSet rs, int rowNum) throws SQLException { 15 | Review review = new Review(); 16 | 17 | review.setId(rs.getInt("review_id")); 18 | review.setCourseName(rs.getString("course_name")); 19 | review.setGivenRating(rs.getDouble("given_rating")); 20 | review.setTitle(rs.getString("title")); 21 | review.setReview(rs.getString("review")); 22 | review.setReviewer(rs.getString("reviewer")); 23 | review.setPostDate(rs.getString("post_date")); 24 | 25 | return review; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/rowMappers/ReviewWithTeacherRowMapper.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.rowMappers; 2 | 3 | import dev.wms.pwrapi.entity.forum.Review; 4 | import dev.wms.pwrapi.entity.forum.Teacher; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.jdbc.core.RowMapper; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | 12 | @Component 13 | public class ReviewWithTeacherRowMapper implements RowMapper { 14 | 15 | private TeacherRowMapper teacherRowMapper; 16 | private ReviewRowMapper reviewRowMapper; 17 | 18 | @Autowired 19 | public ReviewWithTeacherRowMapper(TeacherRowMapper teacherRowMapper, ReviewRowMapper reviewRowMapper){ 20 | this.teacherRowMapper = teacherRowMapper; 21 | this.reviewRowMapper = reviewRowMapper; 22 | } 23 | 24 | @Override 25 | public Review mapRow(ResultSet rs, int rowNum) throws SQLException { 26 | Teacher teacher = teacherRowMapper.mapRow(rs, rowNum); 27 | Review review = reviewRowMapper.mapRow(rs, rowNum); 28 | 29 | review.setTeacher(teacher); 30 | return review; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/forum/rowMappers/TeacherRowMapper.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.forum.rowMappers; 2 | 3 | import dev.wms.pwrapi.entity.forum.Teacher; 4 | import org.springframework.jdbc.core.RowMapper; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | 10 | @Component 11 | public class TeacherRowMapper implements RowMapper { 12 | 13 | @Override 14 | public Teacher mapRow(ResultSet rs, int rowNum) throws SQLException { 15 | Teacher teacher = new Teacher(); 16 | 17 | teacher.setId(rs.getInt("teacher_id")); 18 | teacher.setCategory(rs.getString("category")); 19 | teacher.setFullName(rs.getString("full_name")); 20 | teacher.setAcademicTitle(rs.getString("academic_title")); 21 | teacher.setAverage(rs.getDouble("average_rating")); 22 | 23 | return teacher; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/generalExceptionHandling/GeneralAdvice.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.generalExceptionHandling; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.dto.ExceptionMessagingDTO; 5 | import dev.wms.pwrapi.utils.generalExceptions.InvalidIdException; 6 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 7 | import dev.wms.pwrapi.utils.prowadzacy.exceptions.EmptyResultsException; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.core.Ordered; 10 | import org.springframework.core.annotation.Order; 11 | import org.springframework.http.HttpHeaders; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.http.MediaType; 14 | import org.springframework.http.ResponseEntity; 15 | import org.springframework.web.bind.MissingServletRequestParameterException; 16 | import org.springframework.web.bind.annotation.*; 17 | 18 | import javax.validation.ConstraintViolationException; 19 | 20 | @RestControllerAdvice 21 | @Slf4j 22 | public class GeneralAdvice { 23 | 24 | private static final HttpHeaders headers; 25 | 26 | static{ 27 | headers = new HttpHeaders(); 28 | headers.setContentType(MediaType.APPLICATION_JSON); 29 | } 30 | 31 | @ExceptionHandler(Throwable.class) 32 | @Order(Ordered.LOWEST_PRECEDENCE) 33 | public ResponseEntity handleGeneralException(Throwable t){ 34 | log.info("Handling unexpected exception " + t); 35 | t.printStackTrace(); 36 | return ResponseEntity.status(500).body(new ExceptionMessagingDTO(t.getMessage())); 37 | } 38 | 39 | @ExceptionHandler(ConstraintViolationException.class) 40 | public ResponseEntity handleConstraintViolation(ConstraintViolationException e){ 41 | return ResponseEntity.status(400).body(new ExceptionMessagingDTO(e.getMessage())); 42 | } 43 | 44 | @ExceptionHandler(EmptyResultsException.class) 45 | public ResponseEntity handleEmptyResultsException(EmptyResultsException e){ 46 | return ResponseEntity.status(404).body(new ExceptionMessagingDTO(e.getMessage())); 47 | } 48 | 49 | @ExceptionHandler(MissingServletRequestParameterException.class) 50 | public ResponseEntity handleMissingParameter(MissingServletRequestParameterException e){ 51 | return ResponseEntity.status(400).body(new ExceptionMessagingDTO(e.getMessage())); 52 | } 53 | 54 | @ExceptionHandler(LoginException.class) 55 | public ResponseEntity loginExceptionHandler(LoginException ex) throws JsonProcessingException { 56 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 57 | return new ResponseEntity<>(response, headers, HttpStatus.UNAUTHORIZED); 58 | } 59 | 60 | @ExceptionHandler(InvalidIdException.class) 61 | public ResponseEntity invalidIdExceptionHandler(InvalidIdException ex) throws JsonProcessingException { 62 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 63 | return new ResponseEntity<>(response, headers, HttpStatus.BAD_REQUEST); 64 | } 65 | 66 | @ExceptionHandler(JsonProcessingException.class) 67 | public ResponseEntity jsonProcessingExceptionHandler(JsonProcessingException ex) throws JsonProcessingException { 68 | String response = ResponseMessageHandler.createResponseMessageJSON("Wystąpił błąd, spróbuj ponownie lub skontaktuj się z właścicielem serwisu."); 69 | return new ResponseEntity<>(response, headers, HttpStatus.INTERNAL_SERVER_ERROR); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/generalExceptionHandling/ResponseMessageHandler.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.generalExceptionHandling; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.fasterxml.jackson.databind.ObjectWriter; 6 | import dev.wms.pwrapi.dto.ExceptionMessagingDTO; 7 | 8 | public class ResponseMessageHandler { 9 | /* 10 | class does not use provided ObjectMapperJSON static service, it is a conscious decision 11 | which leads to splitting the mapper associated load (single mapper may be a bottleneck) 12 | */ 13 | private static final ObjectWriter objectWriter = new ObjectMapper().writerWithDefaultPrettyPrinter(); 14 | 15 | public static String createResponseMessageJSON(String message) throws JsonProcessingException { 16 | ExceptionMessagingDTO dto = new ExceptionMessagingDTO(message); 17 | return objectWriter.writeValueAsString(dto); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/generalExceptions/ConstraintViolationExceptionAdvice.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.generalExceptions; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.utils.generalExceptionHandling.ResponseMessageHandler; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.web.bind.annotation.*; 7 | import javax.validation.ConstraintViolationException; 8 | 9 | @RestControllerAdvice 10 | public class ConstraintViolationExceptionAdvice { 11 | 12 | @ResponseBody 13 | @ExceptionHandler(ConstraintViolationException.class) 14 | @ResponseStatus(HttpStatus.BAD_REQUEST) 15 | public String ConstraintExceptionHandler(ConstraintViolationException ex) throws JsonProcessingException { 16 | return ResponseMessageHandler.createResponseMessageJSON(ex.getMessage() 17 | + " Użyłeś parametru, który nie mieści się w dozwolonym zakresie."); 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/generalExceptions/InvalidIdException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.generalExceptions; 2 | 3 | public class InvalidIdException extends RuntimeException { 4 | 5 | public InvalidIdException(long id){ 6 | super("Nieprawidłowe id: " + id + "."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/generalExceptions/LoginException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.generalExceptions; 2 | 3 | public class LoginException extends RuntimeException { 4 | 5 | public LoginException(){ 6 | super("Nieprawidłowy login lub hasło."); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/generalExceptions/SystemTimeoutException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.generalExceptions; 2 | 3 | public class SystemTimeoutException extends RuntimeException{ 4 | public SystemTimeoutException(){ 5 | super("Our API, or university system is under heavy load. Please try again."); 6 | } 7 | } -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/generalExceptions/WrongOrderException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.generalExceptions; 2 | 3 | public class WrongOrderException extends Exception{ 4 | 5 | public WrongOrderException(String message){ 6 | super(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/http/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.http; 2 | 3 | import dev.wms.pwrapi.utils.generalExceptions.SystemTimeoutException; 4 | import okhttp3.OkHttpClient; 5 | import okhttp3.Request; 6 | import okhttp3.Response; 7 | import org.jsoup.Jsoup; 8 | import org.jsoup.nodes.Document; 9 | 10 | import java.io.IOException; 11 | import java.net.SocketTimeoutException; 12 | 13 | public class HttpUtils { 14 | 15 | public static String makeRequestWithClientAndGetString(OkHttpClient client, Request request){ 16 | try(Response response = client.newCall(request).execute()){ 17 | return response.body().string(); 18 | } catch (IOException e) { 19 | throw new RuntimeException(e); 20 | } 21 | } 22 | 23 | public static String makeRequestWithClientAndGetString(OkHttpClient client, String url){ 24 | 25 | Request request = new Request.Builder() 26 | .url(url) 27 | .build(); 28 | 29 | try(Response response = client.newCall(request).execute()){ 30 | return response.body().string(); 31 | } catch (IOException e) { 32 | throw new RuntimeException(e); 33 | } 34 | } 35 | 36 | /** 37 | * Makes request with OkHttp's client and parses it to Jsoup's Document. Needed for proper response closing 38 | * @param client OkHttp client which will execute the request 39 | * @param url URL that will be requested 40 | * @return Jsoup's Document containing parsed html from OkHttp response 41 | * @throws IOException when parsing goes wrong 42 | */ 43 | public static Document makeRequestWithClientAndGetDocument(OkHttpClient client, String url) { 44 | 45 | Request financeRequest = new Request.Builder() 46 | .url(url) 47 | .build(); 48 | 49 | String responseString; 50 | 51 | try(Response response = client.newCall(financeRequest).execute()){ 52 | responseString = response.body().string(); 53 | } catch (SocketTimeoutException e){ 54 | throw new SystemTimeoutException(); 55 | } catch (IOException e) { 56 | throw new RuntimeException(e); 57 | } 58 | 59 | return Jsoup.parse(responseString); 60 | 61 | } 62 | 63 | /** 64 | * Makes request with client and does not return anything. Needed mostly for navigating through the page 65 | * @param client OkHttp client which will execute the request 66 | * @param url URL that will be requested 67 | * @throws IOException when parsing goes wrong 68 | */ 69 | public static void makeRequestWithClient(OkHttpClient client, String url) throws IOException { 70 | 71 | Request financeRequest = new Request.Builder() 72 | .url(url) 73 | .build(); 74 | 75 | try(Response response = client.newCall(financeRequest).execute()){ 76 | 77 | } 78 | 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/jsonProcessing/ObjectMapperJSON.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.jsonProcessing; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | 6 | public class ObjectMapperJSON { 7 | 8 | private static final ObjectMapper objectMapper = new ObjectMapper(); 9 | 10 | public static String writeValueAsString(Object o) throws JsonProcessingException { 11 | return objectMapper.writeValueAsString(o); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/jsos/JsosHttpUtils.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.jsos; 2 | 3 | import dev.wms.pwrapi.dao.jsos.JsosGeneralDAOImpl; 4 | import dev.wms.pwrapi.dto.jsos.JsosConnection; 5 | import okhttp3.OkHttpClient; 6 | 7 | import java.io.IOException; 8 | 9 | public class JsosHttpUtils { 10 | 11 | /** 12 | * Returns logged client instance using JsosGeneralDao 13 | * @param login Login for JSOS 14 | * @param password Password for JSOS 15 | * @return Logged instance of OkHttpClient (on JSOS's main page) 16 | * @throws IOException If parsing goes wrong 17 | */ 18 | public static OkHttpClient getLoggedClient(String login, String password) throws IOException { 19 | 20 | JsosGeneralDAOImpl general = new JsosGeneralDAOImpl(); 21 | JsosConnection jsosConnection = general.login(login, password); 22 | return general.getClient(); 23 | 24 | } 25 | 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/jsos/JsosLessonsUtils.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.jsos; 2 | 3 | import java.io.IOException; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import dev.wms.pwrapi.utils.http.HttpUtils; 8 | import org.jsoup.Jsoup; 9 | import org.jsoup.nodes.Document; 10 | 11 | import okhttp3.OkHttpClient; 12 | import okhttp3.Request; 13 | 14 | public class JsosLessonsUtils { 15 | 16 | 17 | /** 18 | * Just a utils method for determining kind based on the one letter code 19 | * @param className 20 | * @return 21 | */ 22 | public static String determineKindFromClassName(String className){ 23 | 24 | String result; 25 | 26 | List availableClasses = Arrays.asList(new String[]{"W","C","L","P","S","I"}); 27 | List availableResults = Arrays.asList(new String[]{"Wykład", "Ćwiczenia", "Laboratorium", "Projekt", "Seminarium", "Inne"}); 28 | String base = "rozklady_"; 29 | className = className.replace(base, "").split(" ")[0].strip(); 30 | 31 | int index = availableClasses.indexOf(className); 32 | 33 | if(index == -1){ 34 | return "Unidentified type. Please contanct API support"; 35 | } else { 36 | return availableResults.get(availableClasses.indexOf(className)); 37 | } 38 | 39 | } 40 | 41 | /** 42 | * Fetch url of next week 43 | * @param doc Document where we should look for button 44 | * @return URL of next week 45 | */ 46 | public static String getUrlOfNextWeek(Document doc){ 47 | 48 | String result; 49 | result = "https://jsos.pwr.edu.pl" + doc.getElementsByClass("bx-next").get(0).attr("href"); 50 | 51 | return result; 52 | } 53 | 54 | /** 55 | * Fetch url of week with given offset. 56 | * 57 | * Moves forward based on an offset 58 | * @param doc Document where we should look for button 59 | * @param client Logged client for performing requests 60 | * @param offset How many times go forward, can't be negative for going back 61 | * @return URL of offseted week 62 | * @throws IOException If parsing goes wrong 63 | */ 64 | public static String getUrlOfNextWeek(Document doc, OkHttpClient client, int offset) throws IOException{ 65 | 66 | if(offset < 0){ 67 | throw new RuntimeException("Offset cannot be negative in next week method!"); 68 | } 69 | 70 | String result = "https://jsos.pwr.edu.pl/index.php/student/zajecia/tydzien"; 71 | 72 | 73 | for(int i = 0; i < offset; i++){ 74 | result = "https://jsos.pwr.edu.pl" + doc.getElementsByClass("bx-next").get(0).attr("href"); 75 | doc = HttpUtils.makeRequestWithClientAndGetDocument(client, result); 76 | } 77 | 78 | return result; 79 | } 80 | 81 | /** 82 | * Fetch url of previous week 83 | * @param doc Document where we should look for a button 84 | * @return URL of previous week 85 | */ 86 | public static String getUrlOfPreviousWeek(Document doc){ 87 | 88 | String result; 89 | result = "https://jsos.pwr.edu.pl" + doc.getElementsByClass("bx-prev").get(0).attr("href"); 90 | 91 | return result; 92 | } 93 | 94 | /** 95 | * Fetch url of previous week based on the given offset 96 | * Moves back based on an offset 97 | * @param doc Document where we should look for button 98 | * @param client Logged client for performing requests 99 | * @param offset How many times go back 100 | * @return URL of offseted week 101 | * @throws IOException If parsing goes wrong 102 | */ 103 | public static String getUrlOfPreviousWeek(Document doc, OkHttpClient client, int offset) throws IOException{ 104 | 105 | String result = "https://jsos.pwr.edu.pl/index.php/student/zajecia/tydzien"; 106 | if(offset == 0) return getUrlOfPreviousWeek(doc); 107 | 108 | for(int i = 0; i < offset; i++) { 109 | result = "https://jsos.pwr.edu.pl" + doc.getElementsByClass("bx-prev").get(0).attr("href"); 110 | doc = HttpUtils.makeRequestWithClientAndGetDocument(client, result); 111 | } 112 | 113 | return result; 114 | 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/jsos/advice/JsosAPIAdvice.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.jsos.advice; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.utils.generalExceptionHandling.ResponseMessageHandler; 5 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 6 | import dev.wms.pwrapi.utils.jsos.exceptions.NoTodayClassException; 7 | import dev.wms.pwrapi.utils.jsos.exceptions.TooBigOffsetException; 8 | import org.springframework.http.HttpHeaders; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.ExceptionHandler; 13 | import org.springframework.web.bind.annotation.ResponseBody; 14 | import org.springframework.web.bind.annotation.RestControllerAdvice; 15 | 16 | @RestControllerAdvice 17 | public class JsosAPIAdvice { 18 | 19 | private static final HttpHeaders headers; 20 | 21 | static{ 22 | headers = new HttpHeaders(); 23 | headers.setContentType(MediaType.APPLICATION_JSON); 24 | } 25 | 26 | @ExceptionHandler(TooBigOffsetException.class) 27 | public ResponseEntity handleException(TooBigOffsetException e) throws JsonProcessingException { 28 | String response = ResponseMessageHandler.createResponseMessageJSON("Przekroczyłeś(aś) maksymalną wartość przesunięcia dla publicznego API."); 29 | return new ResponseEntity<>(response, headers, HttpStatus.BAD_REQUEST); 30 | } 31 | 32 | @ExceptionHandler(LoginException.class) 33 | public ResponseEntity handleException(LoginException e) throws JsonProcessingException { 34 | String response = ResponseMessageHandler.createResponseMessageJSON("Błędny login, lub hasło."); 35 | return ResponseEntity 36 | .status(HttpStatus.UNAUTHORIZED) 37 | .body(response); 38 | } 39 | 40 | @ExceptionHandler(NoTodayClassException.class) 41 | public ResponseEntity handleException(NoTodayClassException e) throws JsonProcessingException { 42 | String response = ResponseMessageHandler.createResponseMessageJSON("Brak zajęć."); 43 | return ResponseEntity 44 | .status(HttpStatus.UNAUTHORIZED) 45 | .body(response); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/jsos/cookies/CookieJarImpl.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.jsos.cookies; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | 7 | import lombok.Getter; 8 | import okhttp3.Cookie; 9 | import okhttp3.CookieJar; 10 | import okhttp3.HttpUrl; 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | /** 14 | * This is a custom implementation of OkHttp's CookieJar class. It swipes cookies if duplicate is detected 15 | * in order to always have authenticated and most recent cookies given by the server. 16 | * 17 | * Mostly used in accessing services that require OAuth protocol usage. It allows us to quickly swipe 18 | * session cookies and some other tokens. 19 | */ 20 | @Getter 21 | public class CookieJarImpl implements CookieJar{ 22 | 23 | private final HashMap> cookieStore = new HashMap<>(); 24 | 25 | @Override 26 | public void saveFromResponse(HttpUrl url, List cookies) { 27 | 28 | 29 | if(cookieStore.get(url.host()) != null && cookies != null){ 30 | System.out.println("Trying to add cookies " + cookies); 31 | for(Cookie c : cookies){ 32 | 33 | //look for duplicates 34 | for(int i = 0; i < cookieStore.get(url.host()).size(); i++){ 35 | Cookie k = cookieStore.get(url.host()).get(i); 36 | if(c.name().equals(k.name())){ 37 | cookieStore.get(url.host()).remove(k); 38 | i--; 39 | } 40 | System.out.println("Removed duplicate cookie " + c.name()); 41 | } 42 | 43 | cookieStore.get(url.host()).add(c); 44 | 45 | } 46 | } else { 47 | cookieStore.put(url.host(), new ArrayList(cookies)); 48 | } 49 | 50 | System.out.println(cookieStore); 51 | } 52 | 53 | @NotNull 54 | @Override 55 | public List loadForRequest(HttpUrl url) { 56 | List cookies = cookieStore.get(url.host()); 57 | return cookies != null ? cookies : new ArrayList(); 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/jsos/exceptions/NoTodayClassException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.jsos.exceptions; 2 | 3 | public class NoTodayClassException extends Exception{ 4 | 5 | public NoTodayClassException(){ 6 | super("No lectures today."); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/jsos/exceptions/TooBigOffsetException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.jsos.exceptions; 2 | 3 | public class TooBigOffsetException extends Exception{ 4 | 5 | public TooBigOffsetException(){ 6 | super("You have exceeded maximum public API offset."); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/parking/ParkingDateUtils.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.parking; 2 | 3 | import java.time.LocalDateTime; 4 | import java.time.ZoneId; 5 | import java.time.ZonedDateTime; 6 | 7 | public class ParkingDateUtils { 8 | 9 | public static LocalDateTime getDateTimeInPoland(){ 10 | return ZonedDateTime.now() 11 | .withZoneSameInstant(ZoneId.of("Europe/Warsaw")) 12 | .toLocalDateTime(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/parking/ParkingGeneralUtils.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.parking; 2 | 3 | import java.util.Set; 4 | 5 | public class ParkingGeneralUtils { 6 | 7 | /** 8 | * Determines parking based on ID in JSON response from parking server. Returns "Unknown Id" on unknown id 9 | * @param id ID from JSON response 10 | * @return Name of Parking 11 | */ 12 | public static String determineParking(String id){ 13 | 14 | switch (id) { 15 | case "5" -> { 16 | return "D20"; 17 | } 18 | case "4" -> { 19 | return "Parking Wrońskiego"; 20 | } 21 | case "2" -> { 22 | return "C13"; 23 | } 24 | case "6" -> { 25 | return "Geocentrum"; 26 | } 27 | case "7" -> { 28 | return "Architektura"; 29 | } 30 | } 31 | 32 | return "Unknown parking id: " + id; 33 | 34 | } 35 | 36 | public static Set getParkingIds(){ 37 | return Set.of(5,4,2,6,7); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/parking/advice/ParkingAdvice.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.parking.advice; 2 | 3 | import org.springframework.http.HttpHeaders; 4 | import org.springframework.http.MediaType; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.web.bind.annotation.ExceptionHandler; 7 | import org.springframework.web.bind.annotation.ResponseBody; 8 | import org.springframework.web.bind.annotation.ResponseStatus; 9 | 10 | import com.fasterxml.jackson.core.JsonProcessingException; 11 | 12 | import org.springframework.http.HttpStatus; 13 | 14 | import dev.wms.pwrapi.utils.generalExceptionHandling.ResponseMessageHandler; 15 | import dev.wms.pwrapi.utils.parking.exceptions.WrongResponseCode; 16 | import org.springframework.web.bind.annotation.RestControllerAdvice; 17 | 18 | @RestControllerAdvice 19 | public class ParkingAdvice { 20 | 21 | private static final HttpHeaders headers; 22 | 23 | static{ 24 | headers = new HttpHeaders(); 25 | headers.setContentType(MediaType.APPLICATION_JSON); 26 | } 27 | 28 | @ExceptionHandler(WrongResponseCode.class) 29 | public ResponseEntity enrollmentAccessDeniedHandler(WrongResponseCode ex) throws JsonProcessingException { 30 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 31 | return new ResponseEntity<>(response, headers, HttpStatus.INTERNAL_SERVER_ERROR); 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/parking/exceptions/WrongResponseCode.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.parking.exceptions; 2 | 3 | public class WrongResponseCode extends RuntimeException{ 4 | 5 | public WrongResponseCode(){ 6 | super("The university server returned wrong response code. Please contact the administrator."); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/prowadzacy/exceptions/EmptyResultsException.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.prowadzacy.exceptions; 2 | 3 | public class EmptyResultsException extends RuntimeException{ 4 | 5 | public EmptyResultsException(){ 6 | super("Brak wyników. Sprawdź poprawność zapytania"); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/dev/wms/pwrapi/utils/prowadzacy/exceptions/advices/EmptyResultsExceptionAdvice.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.utils.prowadzacy.exceptions.advices; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.utils.generalExceptionHandling.ResponseMessageHandler; 5 | import dev.wms.pwrapi.utils.prowadzacy.exceptions.EmptyResultsException; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.ExceptionHandler; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | import org.springframework.web.bind.annotation.ResponseStatus; 11 | import org.springframework.web.bind.annotation.RestControllerAdvice; 12 | 13 | @RestControllerAdvice 14 | public class EmptyResultsExceptionAdvice { 15 | 16 | @ExceptionHandler(EmptyResultsException.class) 17 | public ResponseEntity ConstraintExceptionHandler(EmptyResultsException ex) throws JsonProcessingException { 18 | String response = ResponseMessageHandler.createResponseMessageJSON(ex.getMessage()); 19 | return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.file.path=./pwr-api-logs 2 | logging.file.name=pwr-api.log 3 | logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG 4 | spring.data.rest.default-media-type=application/json 5 | 6 | pwr-api.news.cacheTTL=900000 -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ${CONSOLE_LOG_PATTERN} 7 | 8 | 9 | 10 | 11 | ./pwr-api-logs/pwr-api.log 12 | 13 | pwr-api-%d{yyyy-MM-dd}.log 14 | 15 | 16 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{0}[%M:%L] - %msg%n 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/PwrApiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PwrApiApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/eportal/EportalUtilsClassesTests.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.eportal; 2 | 3 | import dev.wms.pwrapi.dto.eportal.sections.EportalElementType; 4 | import dev.wms.pwrapi.utils.eportal.EportalGeneralUtils; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | 12 | public class EportalUtilsClassesTests { 13 | 14 | 15 | @Test 16 | public void eportalGeneralUtilsClassShouldReturnInneIfForeignValuePresent(){ 17 | 18 | List imposibleElementTypes = List.of("iAmNotAType", "meNeither", "lolIAmNotAType"); 19 | imposibleElementTypes = imposibleElementTypes.stream() 20 | .map(this::makeUrlFor) 21 | .collect(Collectors.toList()); 22 | 23 | 24 | for(String immposibleType : imposibleElementTypes){ 25 | assertEquals(EportalElementType.INNE, EportalGeneralUtils.determineElementTypeFromUrl(immposibleType)); 26 | } 27 | 28 | } 29 | 30 | 31 | @Test 32 | public void eportalGeneralUtilsClassShouldReturnValueIfPresetInUrl(){ 33 | 34 | List possibleElementTypes = List.of("assign", "pdf", "powerpoint", "core", "url", "page", "archive","reservation", "quiz","other"); 35 | 36 | possibleElementTypes = possibleElementTypes.stream() 37 | .map(this::makeUrlFor) 38 | .collect(Collectors.toList()); 39 | 40 | assertEquals(EportalElementType.ZADANIE, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(0))); 41 | assertEquals(EportalElementType.PDF, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(1))); 42 | assertEquals(EportalElementType.PREZENTACJA, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(2))); 43 | assertEquals(EportalElementType.PLIK, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(3))); 44 | assertEquals(EportalElementType.LINK, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(4))); 45 | assertEquals(EportalElementType.LINK, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(5))); 46 | assertEquals(EportalElementType.ARCHIWUM, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(6))); 47 | assertEquals(EportalElementType.REZERWACJA, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(7))); 48 | assertEquals(EportalElementType.QUIZ, EportalGeneralUtils.determineElementTypeFromUrl(possibleElementTypes.get(8))); 49 | 50 | 51 | } 52 | 53 | private String makeUrlFor(String containing){ 54 | 55 | String urlPrefix = "http://iAmAUrl.com/someStuff/someStuff"; 56 | String urlPostfix = "/yeahPostfix/hello"; 57 | 58 | return urlPrefix + containing + urlPostfix; 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/eportal/WrongCredentialsEportalTests.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.eportal; 2 | 3 | import org.junit.jupiter.api.Disabled; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | import static io.restassured.RestAssured.*; 8 | 9 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 10 | @Disabled("This test cases require good response timings from webiste host") 11 | public class WrongCredentialsEportalTests { 12 | 13 | @Test 14 | public void rootEndpointShouldGive401OnWrongCredentials(){ 15 | 16 | get("api/eportal?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 17 | .assertThat() 18 | .statusCode(401); 19 | 20 | } 21 | 22 | @Test 23 | public void kursyEndpointShouldGive401OnWrongCredentials(){ 24 | 25 | get("api/eportal/kursy?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 26 | .assertThat() 27 | .statusCode(401); 28 | 29 | } 30 | 31 | @Test 32 | public void kursyIdOcenyEndpointShouldGive401OnWrongCredentials(){ 33 | 34 | get("api/eportal/kursy/1/oceny?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 35 | .assertThat() 36 | .statusCode(401); 37 | 38 | } 39 | 40 | @Test 41 | public void kalendarzEndpointShouldGive401OnWrongCredentials(){ 42 | 43 | get("api/eportal/kalendarz?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 44 | .assertThat() 45 | .statusCode(401); 46 | 47 | } 48 | 49 | @Test 50 | public void kalendarzPobierzEndpointShouldGive401OnWrongCredentials(){ 51 | 52 | get("api/eportal/kalendarz/pobierz?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 53 | .assertThat() 54 | .statusCode(401); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/forum/ForumTests.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.forum; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import dev.wms.pwrapi.entity.forum.Teacher; 5 | import dev.wms.pwrapi.service.forum.ForumService; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.boot.test.mock.mockito.MockBean; 9 | import org.springframework.http.HttpStatus; 10 | 11 | import static io.restassured.RestAssured.*; 12 | import static org.hamcrest.Matchers.equalTo; 13 | 14 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 15 | public class ForumTests { 16 | 17 | /* 18 | @MockBean 19 | ForumService forumService; 20 | 21 | @Test 22 | public void metadataEndpointTest(){ 23 | get("api/forum").then() 24 | .assertThat() 25 | .contentType("application/json") 26 | .statusCode(200); 27 | } 28 | 29 | @Test 30 | public void fetchTeacherByIdEndpointTest() throws JsonProcessingException { 31 | Teacher teacher = new Teacher(1, "matematycy", "Prof. dr hab.", "Wojciech Suszko", 5.36); 32 | 33 | get("api/forum/prowadzacy/1").then() 34 | .assertThat() 35 | .contentType("application/json") 36 | .statusCode(200) 37 | .body("id", equalTo(1)) 38 | .body("category", equalTo("matematycy")) 39 | .body("fullName", equalTo("Adam Abrams")); 40 | } 41 | 42 | */ 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/jsos/UtilsClassesTests.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.jsos; 2 | 3 | import dev.wms.pwrapi.testingUtils.TestUtils; 4 | import dev.wms.pwrapi.utils.generalExceptions.LoginException; 5 | import dev.wms.pwrapi.utils.jsos.JsosHttpUtils; 6 | import dev.wms.pwrapi.utils.jsos.JsosLessonsUtils; 7 | import okhttp3.OkHttpClient; 8 | import org.jsoup.nodes.Document; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | import static org.junit.jupiter.api.Assertions.*; 16 | 17 | public class UtilsClassesTests { 18 | 19 | @Test 20 | public void jsosLessonsUtilsNameFromClassMethodTest(){ 21 | 22 | List availableClasses = Arrays.asList(new String[]{"W","C","L","P","S","I"}); 23 | List availableResults = Arrays.asList(new String[]{"Wykład", "Ćwiczenia", "Laboratorium", "Projekt", "Seminarium", "Inne"}); 24 | 25 | for(int i = 0; i < availableClasses.size(); i++){ 26 | assertEquals(JsosLessonsUtils.determineKindFromClassName(availableClasses.get(i)), availableResults.get(i)); 27 | } 28 | } 29 | 30 | @Test 31 | public void jsosLessonsUtilsNameFromClassMethodTestWithPrefix(){ 32 | 33 | List availableClasses = Arrays.asList(new String[]{"W","C","L","P","S","I"}); 34 | List availableResults = Arrays.asList(new String[]{"Wykład", "Ćwiczenia", "Laboratorium", "Projekt", "Seminarium", "Inne"}); 35 | 36 | for(int i = 0; i < availableClasses.size(); i++){ 37 | assertEquals(JsosLessonsUtils.determineKindFromClassName("rozklady_" + availableClasses.get(i)), availableResults.get(i)); 38 | } 39 | } 40 | 41 | @Test 42 | public void jsosLessonsUtilsNameFromClassMethodShouldNotThrowExceptionOnWeirdClass(){ 43 | 44 | List availableClasses = Arrays.asList(new String[]{"W","C","L","P","S","I"}); 45 | List availableResults = Arrays.asList(new String[]{"Wykład", "Ćwiczenia", "Laboratorium", "Projekt", "Seminarium", "Inne"}); 46 | 47 | for(int i = 0; i < availableClasses.size(); i++){ 48 | assertEquals(JsosLessonsUtils.determineKindFromClassName("rozklady_" + availableClasses.get(i)), availableResults.get(i)); 49 | assertDoesNotThrow(() -> JsosLessonsUtils.determineKindFromClassName(TestUtils.generateRandomString(10))); 50 | } 51 | } 52 | 53 | 54 | @Test 55 | public void getUrlOfNextWeekShouldThrowExceptionOnNegativeOffset(){ 56 | 57 | assertThrows(RuntimeException.class, () -> 58 | JsosLessonsUtils.getUrlOfNextWeek(new Document(""), 59 | new OkHttpClient(), 60 | -1)); 61 | 62 | } 63 | 64 | @Test 65 | @Disabled("This test cases require good response timings from webiste host") 66 | public void loginUtilThrowsExceptionOnWrongLoginAndPassword(){ 67 | 68 | assertThrows(LoginException.class, () -> 69 | JsosHttpUtils.getLoggedClient("omgImSuchABadLogin", "omgImSuchABadPassword")); 70 | 71 | } 72 | 73 | 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/jsos/WrongCredentialsJsosTests.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.jsos; 2 | 3 | import org.junit.jupiter.api.Disabled; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | import static io.restassured.RestAssured.*; 8 | 9 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 10 | @Disabled("This test cases require good response timings from webiste host") 11 | public class WrongCredentialsJsosTests { 12 | 13 | @Test 14 | public void rootEndpointShouldGive401OnWrongCredentials(){ 15 | 16 | get("api/jsos?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 17 | .assertThat() 18 | .statusCode(401); 19 | 20 | } 21 | 22 | @Test 23 | public void zajeciaEndpointShouldGive401OnWrongCredentials(){ 24 | 25 | get("api/jsos/zajecia?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 26 | .assertThat() 27 | .statusCode(401); 28 | 29 | } 30 | 31 | @Test 32 | public void zajeciaTydzienEndpointShouldGive401OnWrongCredentials(){ 33 | 34 | get("api/jsos/zajecia/tydzien?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 35 | .assertThat() 36 | .statusCode(401); 37 | 38 | } 39 | 40 | @Test 41 | public void zajeciaTydzienNastepnyEndpointShouldGive401OnWrongCredentials(){ 42 | 43 | get("api/jsos/zajecia/tydzien/nastepny?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 44 | .assertThat() 45 | .statusCode(401); 46 | 47 | } 48 | 49 | @Test 50 | public void zajeciaJutroEndpointShouldGive401OnWrongCredentials(){ 51 | 52 | get("api/jsos/zajecia/jutro?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 53 | .assertThat() 54 | .statusCode(401); 55 | 56 | } 57 | 58 | @Test 59 | public void zajeciaDzisEndpointShouldGive401OnWrongCredentials(){ 60 | 61 | get("api/jsos/zajecia/dzis?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 62 | .assertThat() 63 | .statusCode(401); 64 | 65 | } 66 | 67 | @Test 68 | public void wiadomosciEndpointShouldGive401OnWrongCredentials(){ 69 | 70 | get("api/jsos/wiadomosci/1?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 71 | .assertThat() 72 | .statusCode(401); 73 | 74 | } 75 | 76 | @Test 77 | public void wiadomosciPageTrescEndpointShouldGive401OnWrongCredentials(){ 78 | 79 | get("api/jsos/wiadomosci/1/tresc?login=thisIsNotRealLogin&password=thisIsNotRealPassword&ids=1").then() 80 | .assertThat() 81 | .statusCode(401); 82 | 83 | } 84 | 85 | @Test 86 | public void finanseEndpointShouldGive401OnWrongCredentials(){ 87 | 88 | get("api/jsos/finanse?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 89 | .assertThat() 90 | .statusCode(401); 91 | 92 | } 93 | 94 | @Test 95 | public void finanseOperacjeEndpointShouldGive401OnWrongCredentials(){ 96 | 97 | get("api/jsos/finanse/operacje?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 98 | .assertThat() 99 | .statusCode(401); 100 | 101 | } 102 | 103 | @Test 104 | public void daneEndpointShouldGive401OnWrongCredentials(){ 105 | 106 | get("api/jsos/dane?login=thisIsNotRealLogin&password=thisIsNotRealPassword").then() 107 | .assertThat() 108 | .statusCode(401); 109 | 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/parking/ParkingDAOTest.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.parking; 2 | 3 | import dev.wms.pwrapi.dao.parking.ParkingDAO; 4 | import dev.wms.pwrapi.dto.parking.Parking; 5 | import org.junit.jupiter.api.Disabled; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | 10 | import java.io.IOException; 11 | import java.util.*; 12 | 13 | import static org.junit.jupiter.api.Assertions.assertEquals; 14 | 15 | @SpringBootTest 16 | @Disabled("Disabled because of unexpected changes in SKD system") 17 | public class ParkingDAOTest { 18 | 19 | @Autowired 20 | private ParkingDAO SKDParkingDAO; 21 | 22 | /** 23 | * Because of migration to SKD service, trend feature is no longer supported, and trend should be equal 24 | * to zero 25 | * @throws IOException 26 | */ 27 | @Test 28 | public void trendShouldAlwaysBeZeroFOr() throws IOException { 29 | List result = SKDParkingDAO.getProcessedParkingInfo(); 30 | for(Parking parking : result){ 31 | assertEquals(0, parking.getTrend()); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/parking/ParkingProxySwitchingTest.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.parking; 2 | 3 | import dev.wms.pwrapi.dao.parking.ParkingDAO; 4 | import dev.wms.pwrapi.service.parking.ParkingProxy; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.boot.test.mock.mockito.MockBean; 9 | 10 | import java.io.IOException; 11 | import java.util.Collections; 12 | 13 | import static org.junit.jupiter.api.Assertions.assertEquals; 14 | import static org.junit.jupiter.api.Assertions.assertThrows; 15 | import static org.mockito.Mockito.*; 16 | 17 | @SpringBootTest 18 | public class ParkingProxySwitchingTest { 19 | 20 | @Autowired 21 | private ParkingProxy parkingProxy; 22 | @MockBean(name = "SKDParkingDAO") 23 | private ParkingDAO SKDParkingDAO; 24 | @MockBean(name = "IParkingDAO") 25 | private ParkingDAO IParkingDAO; 26 | 27 | @Test 28 | public void parkingProxyShouldCallSkdServiceIfIparkingIsUnavailable() throws IOException { 29 | when(IParkingDAO.getProcessedParkingInfo()) 30 | .thenThrow(new RuntimeException("Cannot access university system!")); 31 | when(SKDParkingDAO.getProcessedParkingInfo()) 32 | .thenReturn(Collections.emptyList()); 33 | 34 | parkingProxy.getParkingState(); 35 | 36 | verify(SKDParkingDAO, times(1)) 37 | .getProcessedParkingInfo(); 38 | } 39 | 40 | @Test 41 | public void parkingProxyShouldCallSkdServiceIfIparkingIsUnavailableForRawData() throws IOException { 42 | when(IParkingDAO.getRawParkingData()) 43 | .thenThrow(new RuntimeException("Cannot access university system!")); 44 | when(SKDParkingDAO.getRawParkingData()) 45 | .thenReturn(Collections.emptyList()); 46 | 47 | parkingProxy.getParkingWithHistory(); 48 | 49 | verify(SKDParkingDAO, times(1)) 50 | .getRawParkingData(); 51 | } 52 | 53 | 54 | @Test 55 | public void parkingProxyShouldCallIparkingServiceIfIparkingIsAvailable() throws IOException { 56 | when(IParkingDAO.getProcessedParkingInfo()) 57 | .thenReturn(Collections.emptyList()); 58 | when(SKDParkingDAO.getProcessedParkingInfo()) 59 | .thenThrow(new RuntimeException("I shouldn't have been thrown...")); 60 | 61 | parkingProxy.getParkingState(); 62 | 63 | verify(IParkingDAO, times(1)) 64 | .getProcessedParkingInfo(); 65 | 66 | verifyNoInteractions(SKDParkingDAO); 67 | } 68 | 69 | @Test 70 | public void parkingProxyShouldCallIparkingServiceIfIparkingIsAvailableForHistoryEndpoint() throws IOException { 71 | when(IParkingDAO.getRawParkingData()) 72 | .thenReturn(Collections.emptyList()); 73 | when(SKDParkingDAO.getRawParkingData()) 74 | .thenThrow(new RuntimeException("I shouldn't have been thrown...")); 75 | 76 | parkingProxy.getParkingWithHistory(); 77 | 78 | verify(IParkingDAO, times(1)) 79 | .getRawParkingData(); 80 | 81 | verifyNoInteractions(SKDParkingDAO); 82 | } 83 | 84 | 85 | @Test 86 | public void parkingProxyShouldThrowOnBothServicesunavailable() throws IOException { 87 | when(IParkingDAO.getProcessedParkingInfo()) 88 | .thenThrow(new RuntimeException("I'm not working")); 89 | when(SKDParkingDAO.getProcessedParkingInfo()) 90 | .thenThrow(new RuntimeException("I'm not working")); 91 | 92 | assertThrows(Throwable.class, () -> parkingProxy.getParkingState()); 93 | 94 | verify(IParkingDAO, times(1)) 95 | .getProcessedParkingInfo(); 96 | 97 | verify(SKDParkingDAO, times(1)) 98 | .getProcessedParkingInfo(); 99 | } 100 | 101 | @Test 102 | public void parkingProxyShouldThrowOnBothServicesunavailableForHistoryEndpoint() throws IOException { 103 | when(IParkingDAO.getRawParkingData()) 104 | .thenThrow(new RuntimeException("I'm not working")); 105 | when(SKDParkingDAO.getRawParkingData()) 106 | .thenThrow(new RuntimeException("I'm not working")); 107 | 108 | assertThrows(Throwable.class, () -> parkingProxy.getParkingWithHistory()); 109 | 110 | verify(IParkingDAO, times(1)) 111 | .getRawParkingData(); 112 | 113 | verify(SKDParkingDAO, times(1)) 114 | .getRawParkingData(); 115 | } 116 | 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/parking/ParkingProxyTest.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.parking; 2 | 3 | import dev.wms.pwrapi.dto.parking.Parking; 4 | import dev.wms.pwrapi.dto.parking.ParkingWithHistory; 5 | import dev.wms.pwrapi.service.parking.ParkingProxy; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import java.io.IOException; 10 | import java.util.List; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | 14 | @SpringBootTest 15 | public class ParkingProxyTest { 16 | @Autowired 17 | private ParkingProxy parkingProxy; 18 | 19 | @Test 20 | public void parkingProxyShouldntUpdateDataForOneMinute() throws IOException { 21 | List result = parkingProxy.getParkingState(); 22 | for(int i = 0; i < 10; i++){ 23 | assertEquals(result.get(0).getLastUpdate(), parkingProxy.getParkingState().get(0).getLastUpdate()); 24 | } 25 | List resultWithHistory = parkingProxy.getParkingWithHistory(); 26 | for(int i = 0; i < 10; i++){ 27 | assertEquals(resultWithHistory.get(0).getLastUpdate(), parkingProxy.getParkingWithHistory().get(0).getLastUpdate()); 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/parking/ParkingTests.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.parking; 2 | 3 | import io.restassured.http.ContentType; 4 | 5 | import org.hamcrest.Matcher; 6 | import org.junit.jupiter.api.Disabled; 7 | import org.junit.jupiter.api.Test; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | 10 | import static io.restassured.RestAssured.*; 11 | import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath; 12 | import static org.hamcrest.Matchers.*; 13 | 14 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 15 | public class ParkingTests { 16 | 17 | @Test 18 | public void parkingEndpointShouldReturnValueMatchingJsonSchema(){ 19 | 20 | get("/api/parking").then().assertThat() 21 | .body(matchesJsonSchemaInClasspath("parking/parking-schema.json")) 22 | .statusCode(200); 23 | 24 | } 25 | 26 | @Test 27 | public void parkingLeftPlacesShouldContainOnlyPositiveNumbers(){ 28 | 29 | get("api/parking").then() 30 | .body("[0].leftPlaces", greaterThanOrEqualTo(0)) 31 | .body("[1].leftPlaces", greaterThanOrEqualTo(0)) 32 | .body("[2].leftPlaces", greaterThanOrEqualTo(0)) 33 | .body("[3].leftPlaces", greaterThanOrEqualTo(0)) 34 | .body("[4].leftPlaces", greaterThanOrEqualTo(0)); 35 | 36 | } 37 | 38 | @Test 39 | public void allParkingNamesShouldBeAccessible(){ 40 | 41 | get("api/parking").then() 42 | .body("[0].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")) 43 | .body("[1].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")) 44 | .body("[2].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")) 45 | .body("[3].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")) 46 | .body("[4].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")); 47 | 48 | } 49 | 50 | @Test 51 | public void responseTypeShouldBeJSON(){ 52 | get("api/parking").then() 53 | .contentType(ContentType.JSON); 54 | } 55 | 56 | @Test 57 | public void detailsEndpointShouldContainAllParkingNames(){ 58 | 59 | get("api/parking/raw").then() 60 | .body("[0].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")) 61 | .body("[1].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")) 62 | .body("[2].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")) 63 | .body("[3].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")) 64 | .body("[4].name", oneOf("D20", "Parking Wrońskiego", "C13", "Geocentrum", "Architektura")); 65 | 66 | } 67 | 68 | @Test 69 | @Disabled("Disabled because of integrating both iParking and SKD service") 70 | public void historyEndpointShouldBeAnArrayWrappedInString(){ 71 | get("api/parking/raw").then() 72 | .body("[0].history", getArrayMatcher()) 73 | .body("[1].history", getArrayMatcher()) 74 | .body("[2].history", getArrayMatcher()) 75 | .body("[3].history", getArrayMatcher()) 76 | .body("[4].history", getArrayMatcher()); 77 | } 78 | 79 | private Matcher getArrayMatcher(){ 80 | return allOf(startsWith("["), endsWith("]"), not(containsString("(")), not(containsString(")"))); 81 | } 82 | 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/prowadzacy/ProwadzacyTests.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.prowadzacy; 2 | 3 | import dev.wms.pwrapi.api.ParkingAPI; 4 | import io.restassured.http.ContentType; 5 | import io.restassured.module.mockmvc.RestAssuredMockMvc; 6 | 7 | import org.junit.jupiter.api.BeforeAll; 8 | import org.junit.jupiter.api.Test; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | 11 | import static io.restassured.RestAssured.*; 12 | import static io.restassured.matcher.RestAssuredMatchers.*; 13 | import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath; 14 | import static org.hamcrest.Matchers.*; 15 | 16 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 17 | public class ProwadzacyTests { 18 | 19 | @Test 20 | public void szukajEndpoint404OnBadQuery(){ 21 | 22 | get("api/prowadzacy/szukaj?query=omgIamSuchABadQuery&offset=0").then() 23 | .assertThat() 24 | .statusCode(404); 25 | 26 | 27 | } 28 | 29 | @Test 30 | public void szukajEndpointBadRequestOnHugeOffset(){ 31 | 32 | get("api/prowadzacy/szukaj?query=Dariusz Konieczny&offset=10000") 33 | .then().assertThat() 34 | .statusCode(400); 35 | 36 | 37 | } 38 | 39 | @Test 40 | public void szukajEndpointGoodTitleOnGoodQuery(){ 41 | //I hope dariusz konieczny is still working in politechnika... 42 | 43 | get("api/prowadzacy/szukaj?query=Dariusz Konieczny") 44 | .then() 45 | .assertThat() 46 | .body("title", equalTo("Dariusz Konieczny")); 47 | 48 | } 49 | 50 | @Test 51 | public void szukajEndpointShouldWorkOnNoOffset(){ 52 | 53 | get("api/prowadzacy/szukaj?query=omgIamSuchABadQuery") 54 | .then() 55 | .assertThat() 56 | .statusCode(404); 57 | 58 | 59 | } 60 | 61 | @Test 62 | public void szukajEndpointShouldWorkWithOffset(){ 63 | get("api/prowadzacy/szukaj?query=Dariusz Konieczny&offset=-5") 64 | .then() 65 | .assertThat() 66 | .statusCode(200); 67 | 68 | } 69 | 70 | @Test 71 | public void salaEndpointShouldNotWorkWhenOnlyBuildingProvided(){ 72 | get("api/prowadzacy/szukaj/sala?building=D-20") 73 | .then() 74 | .assertThat() 75 | .statusCode(400); 76 | 77 | } 78 | 79 | @Test 80 | public void salaEndpointShouldNotWorkWhenOnlyRoomProvided(){ 81 | 82 | get("api/prowadzacy/szukaj/sala?room=311-d") 83 | .then() 84 | .assertThat() 85 | .statusCode(400); 86 | 87 | } 88 | 89 | @Test 90 | public void salaEndpointShouldReturn404WhenBadQueryReceived(){ 91 | 92 | get("api/prowadzacy/szukaj/sala?building=omgImSuchABadBuilding&room=omgImSuchABadRoom") 93 | .then() 94 | .assertThat() 95 | .statusCode(404); 96 | 97 | 98 | } 99 | 100 | 101 | @Test 102 | public void szukajPrzedmiotEndpointReturnsEmptyOnBadQuery(){ 103 | 104 | get("api/prowadzacy/szukaj/przedmiot?query=omgIamSuchABadQuery").then() 105 | .assertThat() 106 | .statusCode(404); 107 | 108 | 109 | } 110 | 111 | 112 | 113 | 114 | 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/service/news/NewsServiceCachingTest.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.news; 2 | 3 | import dev.wms.pwrapi.dao.news.NewsDAO; 4 | import dev.wms.pwrapi.dto.news.FacultyType; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.boot.test.mock.mockito.MockBean; 9 | 10 | import static org.mockito.ArgumentMatchers.any; 11 | import static org.mockito.Mockito.times; 12 | import static org.mockito.Mockito.verify; 13 | 14 | @SpringBootTest 15 | public class NewsServiceCachingTest { 16 | 17 | @Autowired 18 | private NewsService newsService; 19 | @MockBean 20 | private NewsDAO newsDAO; 21 | 22 | @Test 23 | public void newsDaoShouldBeCalledOnceForMultipleCallsInTTL(){ 24 | for(int i = 0; i < 50; i++) newsService.fetchGeneralNews(); 25 | verify(newsDAO, times(1)) 26 | .parsePwrRSS(any()); 27 | } 28 | 29 | @Test 30 | public void newsDaoShouldBeCalledTwiceForTwoSeparateFacultiesInTTL(){ 31 | for(int i = 0; i < 50; i++){ 32 | newsService.fetchNewsForFaculty(FacultyType.ARCHITEKTURY); 33 | newsService.fetchNewsForFaculty(FacultyType.INFORMATYKI_I_TELEKOMUNIKACJI); 34 | } 35 | 36 | verify(newsDAO, times(1)) 37 | .getFacultyNews(FacultyType.ARCHITEKTURY); 38 | 39 | verify(newsDAO, times(1)) 40 | .getFacultyNews(FacultyType.INFORMATYKI_I_TELEKOMUNIKACJI); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/service/news/NewsServiceTest.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.service.news; 2 | 3 | import dev.wms.pwrapi.dto.news.FacultyType; 4 | import org.junit.jupiter.api.Disabled; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertFalse; 10 | import static org.junit.jupiter.api.Assertions.assertTrue; 11 | 12 | @SpringBootTest 13 | public class NewsServiceTest { 14 | 15 | @Autowired 16 | private NewsService newsService; 17 | 18 | @Test 19 | @Disabled("Disabled because of server protection against foreign IPs (GitHub actions usage)") 20 | public void newsServiceFetchShouldBeNotEmptyForEveryFaculty(){ 21 | for (FacultyType faculty : FacultyType.values()) { 22 | assertFalse(newsService.fetchNewsForFaculty(faculty).getItem().isEmpty()); 23 | } 24 | } 25 | 26 | @Test 27 | @Disabled("Disabled because of server protection against foreign IPs (GitHub actions usage)") 28 | public void newsServiceShouldFetchGeneralNews(){ 29 | assertFalse(newsService.fetchGeneralNews().getItem().isEmpty()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/dev/wms/pwrapi/testingUtils/TestUtils.java: -------------------------------------------------------------------------------- 1 | package dev.wms.pwrapi.testingUtils; 2 | 3 | import java.util.Random; 4 | 5 | public class TestUtils { 6 | 7 | public static String generateRandomString(int length){ 8 | String SALTCHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 9 | StringBuilder salt = new StringBuilder(); 10 | Random rnd = new Random(); 11 | while (salt.length() < length) { 12 | int index = (int) (rnd.nextFloat() * SALTCHARS.length()); 13 | salt.append(SALTCHARS.charAt(index)); 14 | } 15 | String saltStr = salt.toString(); 16 | return saltStr; 17 | } 18 | 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/resources/parking/parking-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "type": "array", 4 | "items": [ 5 | { 6 | "type": "object", 7 | "properties": { 8 | "name": { 9 | "type": "string" 10 | }, 11 | "lastUpdate": { 12 | "type": "string" 13 | }, 14 | "leftPlaces": { 15 | "type": "integer" 16 | }, 17 | "trend": { 18 | "type": "integer" 19 | } 20 | }, 21 | "required": [ 22 | "name", 23 | "lastUpdate", 24 | "leftPlaces", 25 | "trend" 26 | ] 27 | }, 28 | { 29 | "type": "object", 30 | "properties": { 31 | "name": { 32 | "type": "string" 33 | }, 34 | "lastUpdate": { 35 | "type": "string" 36 | }, 37 | "leftPlaces": { 38 | "type": "integer" 39 | }, 40 | "trend": { 41 | "type": "integer" 42 | } 43 | }, 44 | "required": [ 45 | "name", 46 | "lastUpdate", 47 | "leftPlaces", 48 | "trend" 49 | ] 50 | }, 51 | { 52 | "type": "object", 53 | "properties": { 54 | "name": { 55 | "type": "string" 56 | }, 57 | "lastUpdate": { 58 | "type": "string" 59 | }, 60 | "leftPlaces": { 61 | "type": "integer" 62 | }, 63 | "trend": { 64 | "type": "integer" 65 | } 66 | }, 67 | "required": [ 68 | "name", 69 | "lastUpdate", 70 | "leftPlaces", 71 | "trend" 72 | ] 73 | }, 74 | { 75 | "type": "object", 76 | "properties": { 77 | "name": { 78 | "type": "string" 79 | }, 80 | "lastUpdate": { 81 | "type": "string" 82 | }, 83 | "leftPlaces": { 84 | "type": "integer" 85 | }, 86 | "trend": { 87 | "type": "integer" 88 | } 89 | }, 90 | "required": [ 91 | "name", 92 | "lastUpdate", 93 | "leftPlaces", 94 | "trend" 95 | ] 96 | }, 97 | { 98 | "type": "object", 99 | "properties": { 100 | "name": { 101 | "type": "string" 102 | }, 103 | "lastUpdate": { 104 | "type": "string" 105 | }, 106 | "leftPlaces": { 107 | "type": "integer" 108 | }, 109 | "trend": { 110 | "type": "integer" 111 | } 112 | }, 113 | "required": [ 114 | "name", 115 | "lastUpdate", 116 | "leftPlaces", 117 | "trend" 118 | ] 119 | } 120 | ] 121 | } --------------------------------------------------------------------------------