parent
73d6058e18
commit
731f3b70ca
@ -0,0 +1,4 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.rpc.exception; |
||||||
|
|
||||||
|
public class CommonRpcException extends RuntimeException { |
||||||
|
} |
@ -1,59 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<groupId>cn.wustlinghang.wusthelper</groupId> |
|
||||||
<artifactId>graduate</artifactId> |
|
||||||
<version>0.0.1-SNAPSHOT</version> |
|
||||||
<dependencies> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang</groupId> |
|
||||||
<artifactId>mywust-core</artifactId> |
|
||||||
<version>0.0.2-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang</groupId> |
|
||||||
<artifactId>mywust-network-okhttp</artifactId> |
|
||||||
<version>0.0.2-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang.wusthelper</groupId> |
|
||||||
<artifactId>common</artifactId> |
|
||||||
<version>0.0.1-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>jakarta.annotation</groupId> |
|
||||||
<artifactId>jakarta.annotation-api</artifactId> |
|
||||||
<version>2.1.1</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>javax.annotation</groupId> |
|
||||||
<artifactId>javax.annotation-api</artifactId> |
|
||||||
<version>1.3.2</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.projectlombok</groupId> |
|
||||||
<artifactId>lombok</artifactId> |
|
||||||
<version>1.18.26</version> |
|
||||||
<scope>provided</scope> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
<repositories> |
|
||||||
<repository> |
|
||||||
<id>central</id> |
|
||||||
<url>https://repo1.maven.org/maven2</url> |
|
||||||
</repository> |
|
||||||
<repository> |
|
||||||
<snapshots> |
|
||||||
<enabled>true</enabled> |
|
||||||
</snapshots> |
|
||||||
<id>github</id> |
|
||||||
<url>https://maven.pkg.github.com/LingHangStudio/mywust</url> |
|
||||||
</repository> |
|
||||||
</repositories> |
|
||||||
</project> |
|
@ -0,0 +1,54 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/getting-started-jvm . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started-jvm |
||||||
|
# |
||||||
|
# If you want to include the debug port into your docker image |
||||||
|
# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 |
||||||
|
# |
||||||
|
# Then run the container using : |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/getting-started-jvm |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
|
||||||
|
ARG JAVA_PACKAGE=java-11-openjdk-headless |
||||||
|
ARG RUN_JAVA_VERSION=1.3.8 |
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' |
||||||
|
# Install java and the run-java script |
||||||
|
# Also set up permissions for user `1001` |
||||||
|
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ |
||||||
|
&& microdnf update \ |
||||||
|
&& microdnf clean all \ |
||||||
|
&& mkdir /deployments \ |
||||||
|
&& chown 1001 /deployments \ |
||||||
|
&& chmod "g+rwX" /deployments \ |
||||||
|
&& chown 1001:root /deployments \ |
||||||
|
&& curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ |
||||||
|
&& chown 1001 /deployments/run-java.sh \ |
||||||
|
&& chmod 540 /deployments/run-java.sh \ |
||||||
|
&& echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security |
||||||
|
|
||||||
|
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. |
||||||
|
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" |
||||||
|
# We make four distinct layers so if there are application changes the library layers can be re-used |
||||||
|
COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ |
||||||
|
COPY --chown=1001 target/quarkus-app/*.jar /deployments/ |
||||||
|
COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ |
||||||
|
COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
ENTRYPOINT [ "/deployments/run-java.sh" ] |
@ -0,0 +1,51 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Dquarkus.package.type=legacy-jar |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/getting-started-legacy-jar . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started-legacy-jar |
||||||
|
# |
||||||
|
# If you want to include the debug port into your docker image |
||||||
|
# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 |
||||||
|
# |
||||||
|
# Then run the container using : |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/getting-started-legacy-jar |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
|
||||||
|
ARG JAVA_PACKAGE=java-11-openjdk-headless |
||||||
|
ARG RUN_JAVA_VERSION=1.3.8 |
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' |
||||||
|
# Install java and the run-java script |
||||||
|
# Also set up permissions for user `1001` |
||||||
|
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ |
||||||
|
&& microdnf update \ |
||||||
|
&& microdnf clean all \ |
||||||
|
&& mkdir /deployments \ |
||||||
|
&& chown 1001 /deployments \ |
||||||
|
&& chmod "g+rwX" /deployments \ |
||||||
|
&& chown 1001:root /deployments \ |
||||||
|
&& curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ |
||||||
|
&& chown 1001 /deployments/run-java.sh \ |
||||||
|
&& chmod 540 /deployments/run-java.sh \ |
||||||
|
&& echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security |
||||||
|
|
||||||
|
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. |
||||||
|
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" |
||||||
|
COPY target/lib/* /deployments/lib/ |
||||||
|
COPY target/*-runner.jar /deployments/app.jar |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
ENTRYPOINT [ "/deployments/run-java.sh" ] |
@ -0,0 +1,27 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Pnative |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.native -t quarkus/getting-started . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
WORKDIR /work/ |
||||||
|
RUN chown 1001 /work \ |
||||||
|
&& chmod "g+rwX" /work \ |
||||||
|
&& chown 1001:root /work |
||||||
|
COPY --chown=1001:root target/*-runner /work/application |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] |
@ -0,0 +1,23 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Pnative |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/getting-started . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started |
||||||
|
# |
||||||
|
### |
||||||
|
FROM quay.io/quarkus/quarkus-micro-image:1.0 |
||||||
|
COPY target/*-runner /application |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] |
@ -1,7 +0,0 @@ |
|||||||
package cn.wustlinghang; |
|
||||||
|
|
||||||
public class Main { |
|
||||||
public static void main(String[] args) { |
|
||||||
System.out.println("Hello world!"); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,32 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.wusthelper.internal.graduate.services.LoginService; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/cookie") |
||||||
|
public class CookieApi { |
||||||
|
private final LoginService loginService; |
||||||
|
|
||||||
|
public CookieApi(LoginService loginService) { |
||||||
|
this.loginService = loginService; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String login(@QueryParam("username") @NotNull String username, |
||||||
|
@QueryParam("password") @NotNull String password) throws IOException, ApiException { |
||||||
|
return loginService.login(username, password, false); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/verify") |
||||||
|
public Boolean verify(@QueryParam("cookie") @NotNull String cookie) throws IOException { |
||||||
|
return loginService.verify(cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradCourseTableParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradCourseTableApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.Course; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@Path("/course_table") |
||||||
|
@ApplicationScoped |
||||||
|
public class CourseTableApi { |
||||||
|
private final UndergradCourseTableApiService studentInfoApiService; |
||||||
|
private final UndergradCourseTableParser studentInfoPageParser; |
||||||
|
|
||||||
|
public CourseTableApi(UndergradCourseTableApiService studentInfoApiService, |
||||||
|
UndergradCourseTableParser studentInfoPageParser) { |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public List<Course> get(@QueryParam("cookie") @NotNull String cookie, @QueryParam("term") String term) |
||||||
|
throws IOException, ApiException, ParseException { |
||||||
|
String html = studentInfoApiService.getPage(term, cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie, @QueryParam("term") String term) |
||||||
|
throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public List<Course> parse(String html) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradCreditStatusParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradCreditStatusApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/credit_status") |
||||||
|
@ApplicationScoped |
||||||
|
public class CreditStatusApi { |
||||||
|
private final UndergradCreditStatusApiService creditStatusApiService; |
||||||
|
private final UndergradCreditStatusParser creditStatusParser; |
||||||
|
|
||||||
|
private final RequestClientOption option; |
||||||
|
|
||||||
|
public CreditStatusApi(UndergradCreditStatusApiService creditStatusApiService, |
||||||
|
UndergradCreditStatusParser creditStatusParser, |
||||||
|
RequestClientOption option) { |
||||||
|
this.creditStatusApiService = creditStatusApiService; |
||||||
|
this.creditStatusParser = creditStatusParser; |
||||||
|
this.option = option; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = creditStatusApiService.getPage(cookie, option, false); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return creditStatusApiService.getPage(cookie, option, false); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public String parse(String html) throws ParseException { |
||||||
|
return creditStatusParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradScoreParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradScoreApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.Score; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@Path("/score") |
||||||
|
@ApplicationScoped |
||||||
|
public class ScoreApi { |
||||||
|
private final UndergradScoreApiService scoreApiService; |
||||||
|
private final UndergradScoreParser scoreParser; |
||||||
|
|
||||||
|
public ScoreApi(UndergradScoreApiService scoreApiService, UndergradScoreParser scoreParser) { |
||||||
|
this.scoreApiService = scoreApiService; |
||||||
|
this.scoreParser = scoreParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public List<Score> get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = scoreApiService.getPage(cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return scoreApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public List<Score> parse(String html) throws ParseException { |
||||||
|
return scoreParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradStudentInfoPageParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradStudentInfoApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/student_info") |
||||||
|
@ApplicationScoped |
||||||
|
public class StudentInfoApi { |
||||||
|
private final UndergradStudentInfoApiService studentInfoApiService; |
||||||
|
private final UndergradStudentInfoPageParser studentInfoPageParser; |
||||||
|
|
||||||
|
public StudentInfoApi(UndergradStudentInfoApiService studentInfoApiService, |
||||||
|
UndergradStudentInfoPageParser studentInfoPageParser) { |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public StudentInfo get(@QueryParam("cookie") @NotNull String cookie) throws IOException, ApiException, ParseException { |
||||||
|
return this.parse(this.agent(cookie)); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public StudentInfo parse(String html) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradTrainingPlanPageParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradTrainingPlanApiService; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/training_plan") |
||||||
|
@ApplicationScoped |
||||||
|
public class TrainingPlanApi { |
||||||
|
private final UndergradTrainingPlanApiService trainingPlanApiService; |
||||||
|
private final UndergradTrainingPlanPageParser trainingPlanPageParser; |
||||||
|
|
||||||
|
public TrainingPlanApi(UndergradTrainingPlanApiService trainingPlanApiService, |
||||||
|
UndergradTrainingPlanPageParser trainingPlanPageParser) { |
||||||
|
this.trainingPlanApiService = trainingPlanApiService; |
||||||
|
this.trainingPlanPageParser = trainingPlanPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = trainingPlanApiService.getPage(cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return trainingPlanApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public String parse(String html) throws ParseException { |
||||||
|
return trainingPlanPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
|
||||||
|
@Provider |
||||||
|
public class ApiExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<ApiException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ApiException e) { |
||||||
|
return super.toResponse(e.getCodeValue(), e.toString(), "ApiExceptionHandler"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class DefaultExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<Exception> { |
||||||
|
@Override |
||||||
|
public Response toResponse(Exception e) { |
||||||
|
log.error("未知异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"DefaultExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.ws.rs.core.MediaType; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
|
||||||
|
public abstract class ExceptionHandlerBase { |
||||||
|
public static final String EXCEPTION_HEADER_KEY = "X-exception-handler"; |
||||||
|
|
||||||
|
private static final ObjectMapper objectMapper = new ObjectMapper(); |
||||||
|
|
||||||
|
public Response toResponse(ResponseCode code, String msg, String handlerName) { |
||||||
|
return toResponse(code.getCode(), msg, handlerName); |
||||||
|
} |
||||||
|
|
||||||
|
public Response toResponse(int code, String msg, String handlerName) { |
||||||
|
Object response; |
||||||
|
try { |
||||||
|
response = objectMapper.writeValueAsString(RpcResponse.error(code, msg)); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
response = RpcResponse.error(ResponseCode.SERVER_INTERNAL_ERROR); |
||||||
|
} |
||||||
|
|
||||||
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR) |
||||||
|
.entity(response) |
||||||
|
.header(EXCEPTION_HEADER_KEY, handlerName) |
||||||
|
.type(MediaType.APPLICATION_JSON) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class IOExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<IOException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(IOException e) { |
||||||
|
log.error("IO异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"IOExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class ParseExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<ParseException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ParseException e) { |
||||||
|
log.error("解析异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"ParseExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.validation.ValidationException; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class ValidationExceptionHandler extends ExceptionHandlerBase |
||||||
|
implements ExceptionMapper<ValidationException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ValidationException e) { |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.PARAM_WRONG, |
||||||
|
"参数错误:" + e.toString(), |
||||||
|
"ValidationExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.api.json.interceptor; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.internal.graduate.api.json.handler.ExceptionHandlerBase; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.ws.rs.WebApplicationException; |
||||||
|
import jakarta.ws.rs.core.HttpHeaders; |
||||||
|
import jakarta.ws.rs.core.MediaType; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import jakarta.ws.rs.ext.WriterInterceptor; |
||||||
|
import jakarta.ws.rs.ext.WriterInterceptorContext; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Provider |
||||||
|
public class ResponseWrapperInterceptor implements WriterInterceptor { |
||||||
|
private final ObjectMapper objectMapper; |
||||||
|
|
||||||
|
public ResponseWrapperInterceptor(ObjectMapper objectMapper) { |
||||||
|
this.objectMapper = objectMapper; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { |
||||||
|
boolean hasException = context.getHeaders().get(ExceptionHandlerBase.EXCEPTION_HEADER_KEY) != null; |
||||||
|
if (!hasException) { |
||||||
|
Object data = context.getEntity(); |
||||||
|
RpcResponse<Object> wrappedResponse = RpcResponse.success(data); |
||||||
|
String json = objectMapper.writeValueAsString(wrappedResponse); |
||||||
|
context.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); |
||||||
|
context.setEntity(json); |
||||||
|
} |
||||||
|
|
||||||
|
context.proceed(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.bean; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.inject.Singleton; |
||||||
|
|
||||||
|
public class JacksonBean { |
||||||
|
@ApplicationScoped |
||||||
|
public ObjectMapper objectMapper() { |
||||||
|
return new ObjectMapper(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.bean; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.*; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
public class MywustParserBeans { |
||||||
|
@ApplicationScoped |
||||||
|
public UndergradCourseTableParser undergradCourseTableParser() { |
||||||
|
return new UndergradCourseTableParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradScoreParser undergradScoreParser() { |
||||||
|
return new UndergradScoreParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradStudentInfoPageParser undergradStudentInfoPageParser() { |
||||||
|
return new UndergradStudentInfoPageParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradTrainingPlanPageParser undergradTrainingPlanPageParser() { |
||||||
|
return new UndergradTrainingPlanPageParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradCreditStatusParser undergradCreditStatusParser() { |
||||||
|
return new UndergradCreditStatusParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradExamDelayParser undergradExamDelayParser() { |
||||||
|
return new UndergradExamDelayParser(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.bean; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.auth.UndergraduateLogin; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import cn.wustlinghang.mywust.network.Requester; |
||||||
|
import cn.wustlinghang.mywust.network.okhttp.SimpleOkhttpRequester; |
||||||
|
import jakarta.inject.Singleton; |
||||||
|
|
||||||
|
public class MywustRequestAgentBeans { |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public RequestClientOption requestClientOption() { |
||||||
|
RequestClientOption.Proxy proxy = RequestClientOption.Proxy.builder() |
||||||
|
.address("127.0.0.1") |
||||||
|
.port(8080) |
||||||
|
.build(); |
||||||
|
RequestClientOption option = new RequestClientOption(); |
||||||
|
// option.setProxy(proxy);
|
||||||
|
|
||||||
|
return option; |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public Requester requester(RequestClientOption option) { |
||||||
|
return new SimpleOkhttpRequester(option, true); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergraduateLogin undergraduateLogin(Requester requester) { |
||||||
|
return new UndergraduateLogin(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradCourseTableApiService undergradCourseTableApiService(Requester requester) { |
||||||
|
return new UndergradCourseTableApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradScoreApiService undergradScoreApiService(Requester requester) { |
||||||
|
return new UndergradScoreApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradStudentInfoApiService undergradStudentInfoApiService(Requester requester) { |
||||||
|
return new UndergradStudentInfoApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradTrainingPlanApiService undergradTrainingPlanApiService(Requester requester) { |
||||||
|
return new UndergradTrainingPlanApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradCreditStatusApiService undergradCreditStatusApiService(Requester requester) { |
||||||
|
return new UndergradCreditStatusApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradExamDelayApiService undergradExamDelayApiService(Requester requester) { |
||||||
|
return new UndergradExamDelayApiService(requester); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.auth.UndergraduateLogin; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class LoginService { |
||||||
|
private final RequestClientOption option; |
||||||
|
private final UndergraduateLogin undergraduateLogin; |
||||||
|
|
||||||
|
public LoginService(RequestClientOption option, |
||||||
|
UndergraduateLogin undergraduateLogin) { |
||||||
|
this.option = option; |
||||||
|
this.undergraduateLogin = undergraduateLogin; |
||||||
|
} |
||||||
|
|
||||||
|
public String login(String username, String password, boolean legacy) throws IOException, ApiException { |
||||||
|
if (legacy) { |
||||||
|
return undergraduateLogin.getLoginCookieLegacy(username, password, option); |
||||||
|
} else { |
||||||
|
return undergraduateLogin.getLoginCookie(username, password, option); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean verify(String cookie) throws IOException { |
||||||
|
return !undergraduateLogin.checkCookiesFail(cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.data.global.Course; |
||||||
|
import cn.wustlinghang.mywust.data.global.Score; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.data.undergrad.ExamDelayApplication; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class ParseService { |
||||||
|
private final UndergradCourseTableParser courseTableParser; |
||||||
|
private final UndergradScoreParser scoreParser; |
||||||
|
private final UndergradStudentInfoPageParser studentInfoPageParser; |
||||||
|
private final UndergradTrainingPlanPageParser trainingPlanPageParser; |
||||||
|
private final UndergradCreditStatusParser creditStatusParser; |
||||||
|
private final UndergradExamDelayParser examDelayParser; |
||||||
|
|
||||||
|
public ParseService(UndergradCourseTableParser courseTableParser, |
||||||
|
UndergradScoreParser scoreParser, |
||||||
|
UndergradStudentInfoPageParser studentInfoPageParser, |
||||||
|
UndergradTrainingPlanPageParser trainingPlanPageParser, |
||||||
|
UndergradCreditStatusParser creditStatusParser, |
||||||
|
UndergradExamDelayParser examDelayParser) { |
||||||
|
|
||||||
|
this.courseTableParser = courseTableParser; |
||||||
|
this.scoreParser = scoreParser; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
this.trainingPlanPageParser = trainingPlanPageParser; |
||||||
|
this.creditStatusParser = creditStatusParser; |
||||||
|
this.examDelayParser = examDelayParser; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Course> parseCourseTable(String data) throws ParseException { |
||||||
|
return courseTableParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Score> parseScore(String data) throws ParseException { |
||||||
|
return scoreParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public StudentInfo parseStudentInfo(String data) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public String parseTrainingPlan(String data) throws ParseException { |
||||||
|
return trainingPlanPageParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public String parseCreditStatus(String data) throws ParseException { |
||||||
|
return creditStatusParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public List<ExamDelayApplication> parseExamDelayApplications(String data) throws ParseException { |
||||||
|
return examDelayParser.parse(data); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.graduate.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class RequestAgentService { |
||||||
|
private final UndergradCourseTableApiService courseTableApiService; |
||||||
|
private final UndergradScoreApiService scoreApiService; |
||||||
|
private final UndergradStudentInfoApiService studentInfoApiService; |
||||||
|
private final UndergradTrainingPlanApiService trainingPlanApiService; |
||||||
|
private final UndergradCreditStatusApiService creditStatusApiService; |
||||||
|
private final UndergradExamDelayApiService examDelayApiService; |
||||||
|
|
||||||
|
public RequestAgentService(UndergradCourseTableApiService courseTableApiService, |
||||||
|
UndergradScoreApiService scoreApiService, |
||||||
|
UndergradStudentInfoApiService studentInfoApiService, |
||||||
|
UndergradTrainingPlanApiService trainingPlanApiService, |
||||||
|
UndergradCreditStatusApiService creditStatusApiService, |
||||||
|
UndergradExamDelayApiService examDelayApiService) { |
||||||
|
|
||||||
|
this.courseTableApiService = courseTableApiService; |
||||||
|
this.scoreApiService = scoreApiService; |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.trainingPlanApiService = trainingPlanApiService; |
||||||
|
this.creditStatusApiService = creditStatusApiService; |
||||||
|
this.examDelayApiService = examDelayApiService; |
||||||
|
} |
||||||
|
|
||||||
|
public String getStudentInfoPage(String cookie) throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCourseTable(String cookie, String term) throws IOException, ApiException { |
||||||
|
return courseTableApiService.getPage(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getScore(String cookie) throws IOException, ApiException { |
||||||
|
return scoreApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getTrainingPlan(String cookie) throws IOException, ApiException { |
||||||
|
return trainingPlanApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCreditStatus(String cookie) throws IOException, ApiException { |
||||||
|
return creditStatusApiService.getPage(cookie, null, false); |
||||||
|
} |
||||||
|
|
||||||
|
public UndergradExamDelayApiService.ExamActivity[] getExamActivities(String cookie, String term) |
||||||
|
throws IOException, ApiException { |
||||||
|
return examDelayApiService.getActivities(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getExamDelayApplications(String cookie, String term, String activityId) |
||||||
|
throws IOException, ApiException { |
||||||
|
return examDelayApiService.getPage(term, activityId, cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,152 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<title>getting-started - 1.0.0-SNAPSHOT</title> |
||||||
|
<style> |
||||||
|
h1, h2, h3, h4, h5, h6 { |
||||||
|
margin-bottom: 0.5rem; |
||||||
|
font-weight: 400; |
||||||
|
line-height: 1.5; |
||||||
|
} |
||||||
|
|
||||||
|
h1 { |
||||||
|
font-size: 2.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
h2 { |
||||||
|
font-size: 2rem |
||||||
|
} |
||||||
|
|
||||||
|
h3 { |
||||||
|
font-size: 1.75rem |
||||||
|
} |
||||||
|
|
||||||
|
h4 { |
||||||
|
font-size: 1.5rem |
||||||
|
} |
||||||
|
|
||||||
|
h5 { |
||||||
|
font-size: 1.25rem |
||||||
|
} |
||||||
|
|
||||||
|
h6 { |
||||||
|
font-size: 1rem |
||||||
|
} |
||||||
|
|
||||||
|
.lead { |
||||||
|
font-weight: 300; |
||||||
|
font-size: 2rem; |
||||||
|
} |
||||||
|
|
||||||
|
.banner { |
||||||
|
font-size: 2.7rem; |
||||||
|
margin: 0; |
||||||
|
padding: 2rem 1rem; |
||||||
|
background-color: #00A1E2; |
||||||
|
color: white; |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
margin: 0; |
||||||
|
font-family: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; |
||||||
|
} |
||||||
|
|
||||||
|
code { |
||||||
|
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; |
||||||
|
font-size: 87.5%; |
||||||
|
color: #e83e8c; |
||||||
|
word-break: break-word; |
||||||
|
} |
||||||
|
|
||||||
|
.left-column { |
||||||
|
padding: .75rem; |
||||||
|
max-width: 75%; |
||||||
|
min-width: 55%; |
||||||
|
} |
||||||
|
|
||||||
|
.right-column { |
||||||
|
padding: .75rem; |
||||||
|
max-width: 25%; |
||||||
|
} |
||||||
|
|
||||||
|
.container { |
||||||
|
display: flex; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
li { |
||||||
|
margin: 0.75rem; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section { |
||||||
|
margin-left: 1rem; |
||||||
|
padding-left: 0.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section h3 { |
||||||
|
padding-top: 0; |
||||||
|
font-weight: 200; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section ul { |
||||||
|
border-left: 0.3rem solid #00A1E2; |
||||||
|
list-style-type: none; |
||||||
|
padding-left: 0; |
||||||
|
} |
||||||
|
|
||||||
|
</style> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
|
||||||
|
<div class="banner lead"> |
||||||
|
Your new Cloud-Native application is ready! |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="container"> |
||||||
|
<div class="left-column"> |
||||||
|
<p class="lead"> Congratulations, you have created a new Quarkus application.</p> |
||||||
|
|
||||||
|
<h2>Why do you see this?</h2> |
||||||
|
|
||||||
|
<p>This page is served by Quarkus. The source is in |
||||||
|
<code>src/main/resources/META-INF/resources/index.html</code>.</p> |
||||||
|
|
||||||
|
<h2>What can I do from here?</h2> |
||||||
|
|
||||||
|
<p>If not already done, run the application in <em>dev mode</em> using: <code>mvn quarkus:dev</code>. |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li>Add REST resources, Servlets, functions and other services in <code>src/main/java</code>.</li> |
||||||
|
<li>Your static assets are located in <code>src/main/resources/META-INF/resources</code>.</li> |
||||||
|
<li>Configure your application in <code>src/main/resources/application.properties</code>. |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
<h2>How do I get rid of this page?</h2> |
||||||
|
<p>Just delete the <code>src/main/resources/META-INF/resources/index.html</code> file.</p> |
||||||
|
</div> |
||||||
|
<div class="right-column"> |
||||||
|
<div class="right-section"> |
||||||
|
<h3>Application</h3> |
||||||
|
<ul> |
||||||
|
<li>GroupId: org.acme</li> |
||||||
|
<li>ArtifactId: getting-started</li> |
||||||
|
<li>Version: 1.0.0-SNAPSHOT</li> |
||||||
|
<li>Quarkus Version: 0.11.0</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div class="right-section"> |
||||||
|
<h3>Next steps</h3> |
||||||
|
<ul> |
||||||
|
<li><a href="https://quarkus.io/guides/maven-tooling.html">Setup your IDE</a></li> |
||||||
|
<li><a href="https://quarkus.io/guides/getting-started-guide.html">Getting started</a></li> |
||||||
|
<li><a href="https://quarkus.io">Quarkus Web Site</a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,11 @@ |
|||||||
|
quarkus.http.port=22800 |
||||||
|
#quarkus.log.level=DEBUG |
||||||
|
quarkus.log.file.encoding=UTF-8 |
||||||
|
|
||||||
|
# 打包成jar时附带依赖 |
||||||
|
quarkus.package.type=uber-jar |
||||||
|
|
||||||
|
# 原生镜像编译附加参数,去掉后编译会失败 |
||||||
|
# 但也只是能编译完成,目前的编译产物完全不可用,有非常多的严重bug |
||||||
|
# 现阶段使用jar运行,启动效率虽不如原生程序,但速度尚可 |
||||||
|
quarkus.native.additional-build-args="--initialize-at-run-time=cn.wustlinghang.mywust" |
@ -1,59 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<groupId>cn.wustlinghang.wusthelper</groupId> |
|
||||||
<artifactId>library</artifactId> |
|
||||||
<version>0.0.1-SNAPSHOT</version> |
|
||||||
<dependencies> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang</groupId> |
|
||||||
<artifactId>mywust-core</artifactId> |
|
||||||
<version>0.0.2-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang</groupId> |
|
||||||
<artifactId>mywust-network-okhttp</artifactId> |
|
||||||
<version>0.0.2-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang.wusthelper</groupId> |
|
||||||
<artifactId>common</artifactId> |
|
||||||
<version>0.0.1-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>jakarta.annotation</groupId> |
|
||||||
<artifactId>jakarta.annotation-api</artifactId> |
|
||||||
<version>2.1.1</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>javax.annotation</groupId> |
|
||||||
<artifactId>javax.annotation-api</artifactId> |
|
||||||
<version>1.3.2</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.projectlombok</groupId> |
|
||||||
<artifactId>lombok</artifactId> |
|
||||||
<version>1.18.26</version> |
|
||||||
<scope>provided</scope> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
<repositories> |
|
||||||
<repository> |
|
||||||
<id>central</id> |
|
||||||
<url>https://repo1.maven.org/maven2</url> |
|
||||||
</repository> |
|
||||||
<repository> |
|
||||||
<snapshots> |
|
||||||
<enabled>true</enabled> |
|
||||||
</snapshots> |
|
||||||
<id>github</id> |
|
||||||
<url>https://maven.pkg.github.com/LingHangStudio/mywust</url> |
|
||||||
</repository> |
|
||||||
</repositories> |
|
||||||
</project> |
|
@ -0,0 +1,54 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/getting-started-jvm . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started-jvm |
||||||
|
# |
||||||
|
# If you want to include the debug port into your docker image |
||||||
|
# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 |
||||||
|
# |
||||||
|
# Then run the container using : |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/getting-started-jvm |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
|
||||||
|
ARG JAVA_PACKAGE=java-11-openjdk-headless |
||||||
|
ARG RUN_JAVA_VERSION=1.3.8 |
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' |
||||||
|
# Install java and the run-java script |
||||||
|
# Also set up permissions for user `1001` |
||||||
|
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ |
||||||
|
&& microdnf update \ |
||||||
|
&& microdnf clean all \ |
||||||
|
&& mkdir /deployments \ |
||||||
|
&& chown 1001 /deployments \ |
||||||
|
&& chmod "g+rwX" /deployments \ |
||||||
|
&& chown 1001:root /deployments \ |
||||||
|
&& curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ |
||||||
|
&& chown 1001 /deployments/run-java.sh \ |
||||||
|
&& chmod 540 /deployments/run-java.sh \ |
||||||
|
&& echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security |
||||||
|
|
||||||
|
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. |
||||||
|
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" |
||||||
|
# We make four distinct layers so if there are application changes the library layers can be re-used |
||||||
|
COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ |
||||||
|
COPY --chown=1001 target/quarkus-app/*.jar /deployments/ |
||||||
|
COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ |
||||||
|
COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
ENTRYPOINT [ "/deployments/run-java.sh" ] |
@ -0,0 +1,51 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Dquarkus.package.type=legacy-jar |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/getting-started-legacy-jar . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started-legacy-jar |
||||||
|
# |
||||||
|
# If you want to include the debug port into your docker image |
||||||
|
# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 |
||||||
|
# |
||||||
|
# Then run the container using : |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/getting-started-legacy-jar |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
|
||||||
|
ARG JAVA_PACKAGE=java-11-openjdk-headless |
||||||
|
ARG RUN_JAVA_VERSION=1.3.8 |
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' |
||||||
|
# Install java and the run-java script |
||||||
|
# Also set up permissions for user `1001` |
||||||
|
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ |
||||||
|
&& microdnf update \ |
||||||
|
&& microdnf clean all \ |
||||||
|
&& mkdir /deployments \ |
||||||
|
&& chown 1001 /deployments \ |
||||||
|
&& chmod "g+rwX" /deployments \ |
||||||
|
&& chown 1001:root /deployments \ |
||||||
|
&& curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ |
||||||
|
&& chown 1001 /deployments/run-java.sh \ |
||||||
|
&& chmod 540 /deployments/run-java.sh \ |
||||||
|
&& echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security |
||||||
|
|
||||||
|
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. |
||||||
|
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" |
||||||
|
COPY target/lib/* /deployments/lib/ |
||||||
|
COPY target/*-runner.jar /deployments/app.jar |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
ENTRYPOINT [ "/deployments/run-java.sh" ] |
@ -0,0 +1,27 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Pnative |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.native -t quarkus/getting-started . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
WORKDIR /work/ |
||||||
|
RUN chown 1001 /work \ |
||||||
|
&& chmod "g+rwX" /work \ |
||||||
|
&& chown 1001:root /work |
||||||
|
COPY --chown=1001:root target/*-runner /work/application |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] |
@ -0,0 +1,23 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Pnative |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/getting-started . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started |
||||||
|
# |
||||||
|
### |
||||||
|
FROM quay.io/quarkus/quarkus-micro-image:1.0 |
||||||
|
COPY target/*-runner /application |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] |
@ -1,7 +0,0 @@ |
|||||||
package cn.wustlinghang; |
|
||||||
|
|
||||||
public class Main { |
|
||||||
public static void main(String[] args) { |
|
||||||
System.out.println("Hello world!"); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,32 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.wusthelper.internal.library.services.LoginService; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/cookie") |
||||||
|
public class CookieApi { |
||||||
|
private final LoginService loginService; |
||||||
|
|
||||||
|
public CookieApi(LoginService loginService) { |
||||||
|
this.loginService = loginService; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String login(@QueryParam("username") @NotNull String username, |
||||||
|
@QueryParam("password") @NotNull String password) throws IOException, ApiException { |
||||||
|
return loginService.login(username, password, false); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/verify") |
||||||
|
public Boolean verify(@QueryParam("cookie") @NotNull String cookie) throws IOException { |
||||||
|
return loginService.verify(cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradCourseTableParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradCourseTableApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.Course; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@Path("/course_table") |
||||||
|
@ApplicationScoped |
||||||
|
public class CourseTableApi { |
||||||
|
private final UndergradCourseTableApiService studentInfoApiService; |
||||||
|
private final UndergradCourseTableParser studentInfoPageParser; |
||||||
|
|
||||||
|
public CourseTableApi(UndergradCourseTableApiService studentInfoApiService, |
||||||
|
UndergradCourseTableParser studentInfoPageParser) { |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public List<Course> get(@QueryParam("cookie") @NotNull String cookie, @QueryParam("term") String term) |
||||||
|
throws IOException, ApiException, ParseException { |
||||||
|
String html = studentInfoApiService.getPage(term, cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie, @QueryParam("term") String term) |
||||||
|
throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public List<Course> parse(String html) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradCreditStatusParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradCreditStatusApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/credit_status") |
||||||
|
@ApplicationScoped |
||||||
|
public class CreditStatusApi { |
||||||
|
private final UndergradCreditStatusApiService creditStatusApiService; |
||||||
|
private final UndergradCreditStatusParser creditStatusParser; |
||||||
|
|
||||||
|
private final RequestClientOption option; |
||||||
|
|
||||||
|
public CreditStatusApi(UndergradCreditStatusApiService creditStatusApiService, |
||||||
|
UndergradCreditStatusParser creditStatusParser, |
||||||
|
RequestClientOption option) { |
||||||
|
this.creditStatusApiService = creditStatusApiService; |
||||||
|
this.creditStatusParser = creditStatusParser; |
||||||
|
this.option = option; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = creditStatusApiService.getPage(cookie, option, false); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return creditStatusApiService.getPage(cookie, option, false); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public String parse(String html) throws ParseException { |
||||||
|
return creditStatusParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradScoreParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradScoreApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.Score; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@Path("/score") |
||||||
|
@ApplicationScoped |
||||||
|
public class ScoreApi { |
||||||
|
private final UndergradScoreApiService scoreApiService; |
||||||
|
private final UndergradScoreParser scoreParser; |
||||||
|
|
||||||
|
public ScoreApi(UndergradScoreApiService scoreApiService, UndergradScoreParser scoreParser) { |
||||||
|
this.scoreApiService = scoreApiService; |
||||||
|
this.scoreParser = scoreParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public List<Score> get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = scoreApiService.getPage(cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return scoreApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public List<Score> parse(String html) throws ParseException { |
||||||
|
return scoreParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradStudentInfoPageParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradStudentInfoApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/student_info") |
||||||
|
@ApplicationScoped |
||||||
|
public class StudentInfoApi { |
||||||
|
private final UndergradStudentInfoApiService studentInfoApiService; |
||||||
|
private final UndergradStudentInfoPageParser studentInfoPageParser; |
||||||
|
|
||||||
|
public StudentInfoApi(UndergradStudentInfoApiService studentInfoApiService, |
||||||
|
UndergradStudentInfoPageParser studentInfoPageParser) { |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public StudentInfo get(@QueryParam("cookie") @NotNull String cookie) throws IOException, ApiException, ParseException { |
||||||
|
return this.parse(this.agent(cookie)); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public StudentInfo parse(String html) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradTrainingPlanPageParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradTrainingPlanApiService; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/training_plan") |
||||||
|
@ApplicationScoped |
||||||
|
public class TrainingPlanApi { |
||||||
|
private final UndergradTrainingPlanApiService trainingPlanApiService; |
||||||
|
private final UndergradTrainingPlanPageParser trainingPlanPageParser; |
||||||
|
|
||||||
|
public TrainingPlanApi(UndergradTrainingPlanApiService trainingPlanApiService, |
||||||
|
UndergradTrainingPlanPageParser trainingPlanPageParser) { |
||||||
|
this.trainingPlanApiService = trainingPlanApiService; |
||||||
|
this.trainingPlanPageParser = trainingPlanPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = trainingPlanApiService.getPage(cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return trainingPlanApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public String parse(String html) throws ParseException { |
||||||
|
return trainingPlanPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
|
||||||
|
@Provider |
||||||
|
public class ApiExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<ApiException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ApiException e) { |
||||||
|
return super.toResponse(e.getCodeValue(), e.toString(), "ApiExceptionHandler"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class DefaultExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<Exception> { |
||||||
|
@Override |
||||||
|
public Response toResponse(Exception e) { |
||||||
|
log.error("未知异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"DefaultExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.ws.rs.core.MediaType; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
|
||||||
|
public abstract class ExceptionHandlerBase { |
||||||
|
public static final String EXCEPTION_HEADER_KEY = "X-exception-handler"; |
||||||
|
|
||||||
|
private static final ObjectMapper objectMapper = new ObjectMapper(); |
||||||
|
|
||||||
|
public Response toResponse(ResponseCode code, String msg, String handlerName) { |
||||||
|
return toResponse(code.getCode(), msg, handlerName); |
||||||
|
} |
||||||
|
|
||||||
|
public Response toResponse(int code, String msg, String handlerName) { |
||||||
|
Object response; |
||||||
|
try { |
||||||
|
response = objectMapper.writeValueAsString(RpcResponse.error(code, msg)); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
response = RpcResponse.error(ResponseCode.SERVER_INTERNAL_ERROR); |
||||||
|
} |
||||||
|
|
||||||
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR) |
||||||
|
.entity(response) |
||||||
|
.header(EXCEPTION_HEADER_KEY, handlerName) |
||||||
|
.type(MediaType.APPLICATION_JSON) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class IOExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<IOException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(IOException e) { |
||||||
|
log.error("IO异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"IOExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class ParseExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<ParseException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ParseException e) { |
||||||
|
log.error("解析异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"ParseExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.validation.ValidationException; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class ValidationExceptionHandler extends ExceptionHandlerBase |
||||||
|
implements ExceptionMapper<ValidationException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ValidationException e) { |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.PARAM_WRONG, |
||||||
|
"参数错误:" + e.toString(), |
||||||
|
"ValidationExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.api.json.interceptor; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.internal.library.api.json.handler.ExceptionHandlerBase; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.ws.rs.WebApplicationException; |
||||||
|
import jakarta.ws.rs.core.HttpHeaders; |
||||||
|
import jakarta.ws.rs.core.MediaType; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import jakarta.ws.rs.ext.WriterInterceptor; |
||||||
|
import jakarta.ws.rs.ext.WriterInterceptorContext; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Provider |
||||||
|
public class ResponseWrapperInterceptor implements WriterInterceptor { |
||||||
|
private final ObjectMapper objectMapper; |
||||||
|
|
||||||
|
public ResponseWrapperInterceptor(ObjectMapper objectMapper) { |
||||||
|
this.objectMapper = objectMapper; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { |
||||||
|
boolean hasException = context.getHeaders().get(ExceptionHandlerBase.EXCEPTION_HEADER_KEY) != null; |
||||||
|
if (!hasException) { |
||||||
|
Object data = context.getEntity(); |
||||||
|
RpcResponse<Object> wrappedResponse = RpcResponse.success(data); |
||||||
|
String json = objectMapper.writeValueAsString(wrappedResponse); |
||||||
|
context.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); |
||||||
|
context.setEntity(json); |
||||||
|
} |
||||||
|
|
||||||
|
context.proceed(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.bean; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.inject.Singleton; |
||||||
|
|
||||||
|
public class JacksonBean { |
||||||
|
@ApplicationScoped |
||||||
|
public ObjectMapper objectMapper() { |
||||||
|
return new ObjectMapper(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.bean; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.*; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
public class MywustParserBeans { |
||||||
|
@ApplicationScoped |
||||||
|
public UndergradCourseTableParser undergradCourseTableParser() { |
||||||
|
return new UndergradCourseTableParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradScoreParser undergradScoreParser() { |
||||||
|
return new UndergradScoreParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradStudentInfoPageParser undergradStudentInfoPageParser() { |
||||||
|
return new UndergradStudentInfoPageParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradTrainingPlanPageParser undergradTrainingPlanPageParser() { |
||||||
|
return new UndergradTrainingPlanPageParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradCreditStatusParser undergradCreditStatusParser() { |
||||||
|
return new UndergradCreditStatusParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradExamDelayParser undergradExamDelayParser() { |
||||||
|
return new UndergradExamDelayParser(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.bean; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.auth.UndergraduateLogin; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import cn.wustlinghang.mywust.network.Requester; |
||||||
|
import cn.wustlinghang.mywust.network.okhttp.SimpleOkhttpRequester; |
||||||
|
import jakarta.inject.Singleton; |
||||||
|
|
||||||
|
public class MywustRequestAgentBeans { |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public RequestClientOption requestClientOption() { |
||||||
|
RequestClientOption.Proxy proxy = RequestClientOption.Proxy.builder() |
||||||
|
.address("127.0.0.1") |
||||||
|
.port(8080) |
||||||
|
.build(); |
||||||
|
RequestClientOption option = new RequestClientOption(); |
||||||
|
// option.setProxy(proxy);
|
||||||
|
|
||||||
|
return option; |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public Requester requester(RequestClientOption option) { |
||||||
|
return new SimpleOkhttpRequester(option, true); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergraduateLogin undergraduateLogin(Requester requester) { |
||||||
|
return new UndergraduateLogin(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradCourseTableApiService undergradCourseTableApiService(Requester requester) { |
||||||
|
return new UndergradCourseTableApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradScoreApiService undergradScoreApiService(Requester requester) { |
||||||
|
return new UndergradScoreApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradStudentInfoApiService undergradStudentInfoApiService(Requester requester) { |
||||||
|
return new UndergradStudentInfoApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradTrainingPlanApiService undergradTrainingPlanApiService(Requester requester) { |
||||||
|
return new UndergradTrainingPlanApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradCreditStatusApiService undergradCreditStatusApiService(Requester requester) { |
||||||
|
return new UndergradCreditStatusApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradExamDelayApiService undergradExamDelayApiService(Requester requester) { |
||||||
|
return new UndergradExamDelayApiService(requester); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.auth.UndergraduateLogin; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class LoginService { |
||||||
|
private final RequestClientOption option; |
||||||
|
private final UndergraduateLogin undergraduateLogin; |
||||||
|
|
||||||
|
public LoginService(RequestClientOption option, |
||||||
|
UndergraduateLogin undergraduateLogin) { |
||||||
|
this.option = option; |
||||||
|
this.undergraduateLogin = undergraduateLogin; |
||||||
|
} |
||||||
|
|
||||||
|
public String login(String username, String password, boolean legacy) throws IOException, ApiException { |
||||||
|
if (legacy) { |
||||||
|
return undergraduateLogin.getLoginCookieLegacy(username, password, option); |
||||||
|
} else { |
||||||
|
return undergraduateLogin.getLoginCookie(username, password, option); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean verify(String cookie) throws IOException { |
||||||
|
return !undergraduateLogin.checkCookiesFail(cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.data.global.Course; |
||||||
|
import cn.wustlinghang.mywust.data.global.Score; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.data.undergrad.ExamDelayApplication; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class ParseService { |
||||||
|
private final UndergradCourseTableParser courseTableParser; |
||||||
|
private final UndergradScoreParser scoreParser; |
||||||
|
private final UndergradStudentInfoPageParser studentInfoPageParser; |
||||||
|
private final UndergradTrainingPlanPageParser trainingPlanPageParser; |
||||||
|
private final UndergradCreditStatusParser creditStatusParser; |
||||||
|
private final UndergradExamDelayParser examDelayParser; |
||||||
|
|
||||||
|
public ParseService(UndergradCourseTableParser courseTableParser, |
||||||
|
UndergradScoreParser scoreParser, |
||||||
|
UndergradStudentInfoPageParser studentInfoPageParser, |
||||||
|
UndergradTrainingPlanPageParser trainingPlanPageParser, |
||||||
|
UndergradCreditStatusParser creditStatusParser, |
||||||
|
UndergradExamDelayParser examDelayParser) { |
||||||
|
|
||||||
|
this.courseTableParser = courseTableParser; |
||||||
|
this.scoreParser = scoreParser; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
this.trainingPlanPageParser = trainingPlanPageParser; |
||||||
|
this.creditStatusParser = creditStatusParser; |
||||||
|
this.examDelayParser = examDelayParser; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Course> parseCourseTable(String data) throws ParseException { |
||||||
|
return courseTableParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Score> parseScore(String data) throws ParseException { |
||||||
|
return scoreParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public StudentInfo parseStudentInfo(String data) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public String parseTrainingPlan(String data) throws ParseException { |
||||||
|
return trainingPlanPageParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public String parseCreditStatus(String data) throws ParseException { |
||||||
|
return creditStatusParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public List<ExamDelayApplication> parseExamDelayApplications(String data) throws ParseException { |
||||||
|
return examDelayParser.parse(data); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.library.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class RequestAgentService { |
||||||
|
private final UndergradCourseTableApiService courseTableApiService; |
||||||
|
private final UndergradScoreApiService scoreApiService; |
||||||
|
private final UndergradStudentInfoApiService studentInfoApiService; |
||||||
|
private final UndergradTrainingPlanApiService trainingPlanApiService; |
||||||
|
private final UndergradCreditStatusApiService creditStatusApiService; |
||||||
|
private final UndergradExamDelayApiService examDelayApiService; |
||||||
|
|
||||||
|
public RequestAgentService(UndergradCourseTableApiService courseTableApiService, |
||||||
|
UndergradScoreApiService scoreApiService, |
||||||
|
UndergradStudentInfoApiService studentInfoApiService, |
||||||
|
UndergradTrainingPlanApiService trainingPlanApiService, |
||||||
|
UndergradCreditStatusApiService creditStatusApiService, |
||||||
|
UndergradExamDelayApiService examDelayApiService) { |
||||||
|
|
||||||
|
this.courseTableApiService = courseTableApiService; |
||||||
|
this.scoreApiService = scoreApiService; |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.trainingPlanApiService = trainingPlanApiService; |
||||||
|
this.creditStatusApiService = creditStatusApiService; |
||||||
|
this.examDelayApiService = examDelayApiService; |
||||||
|
} |
||||||
|
|
||||||
|
public String getStudentInfoPage(String cookie) throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCourseTable(String cookie, String term) throws IOException, ApiException { |
||||||
|
return courseTableApiService.getPage(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getScore(String cookie) throws IOException, ApiException { |
||||||
|
return scoreApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getTrainingPlan(String cookie) throws IOException, ApiException { |
||||||
|
return trainingPlanApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCreditStatus(String cookie) throws IOException, ApiException { |
||||||
|
return creditStatusApiService.getPage(cookie, null, false); |
||||||
|
} |
||||||
|
|
||||||
|
public UndergradExamDelayApiService.ExamActivity[] getExamActivities(String cookie, String term) |
||||||
|
throws IOException, ApiException { |
||||||
|
return examDelayApiService.getActivities(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getExamDelayApplications(String cookie, String term, String activityId) |
||||||
|
throws IOException, ApiException { |
||||||
|
return examDelayApiService.getPage(term, activityId, cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,152 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<title>getting-started - 1.0.0-SNAPSHOT</title> |
||||||
|
<style> |
||||||
|
h1, h2, h3, h4, h5, h6 { |
||||||
|
margin-bottom: 0.5rem; |
||||||
|
font-weight: 400; |
||||||
|
line-height: 1.5; |
||||||
|
} |
||||||
|
|
||||||
|
h1 { |
||||||
|
font-size: 2.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
h2 { |
||||||
|
font-size: 2rem |
||||||
|
} |
||||||
|
|
||||||
|
h3 { |
||||||
|
font-size: 1.75rem |
||||||
|
} |
||||||
|
|
||||||
|
h4 { |
||||||
|
font-size: 1.5rem |
||||||
|
} |
||||||
|
|
||||||
|
h5 { |
||||||
|
font-size: 1.25rem |
||||||
|
} |
||||||
|
|
||||||
|
h6 { |
||||||
|
font-size: 1rem |
||||||
|
} |
||||||
|
|
||||||
|
.lead { |
||||||
|
font-weight: 300; |
||||||
|
font-size: 2rem; |
||||||
|
} |
||||||
|
|
||||||
|
.banner { |
||||||
|
font-size: 2.7rem; |
||||||
|
margin: 0; |
||||||
|
padding: 2rem 1rem; |
||||||
|
background-color: #00A1E2; |
||||||
|
color: white; |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
margin: 0; |
||||||
|
font-family: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; |
||||||
|
} |
||||||
|
|
||||||
|
code { |
||||||
|
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; |
||||||
|
font-size: 87.5%; |
||||||
|
color: #e83e8c; |
||||||
|
word-break: break-word; |
||||||
|
} |
||||||
|
|
||||||
|
.left-column { |
||||||
|
padding: .75rem; |
||||||
|
max-width: 75%; |
||||||
|
min-width: 55%; |
||||||
|
} |
||||||
|
|
||||||
|
.right-column { |
||||||
|
padding: .75rem; |
||||||
|
max-width: 25%; |
||||||
|
} |
||||||
|
|
||||||
|
.container { |
||||||
|
display: flex; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
li { |
||||||
|
margin: 0.75rem; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section { |
||||||
|
margin-left: 1rem; |
||||||
|
padding-left: 0.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section h3 { |
||||||
|
padding-top: 0; |
||||||
|
font-weight: 200; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section ul { |
||||||
|
border-left: 0.3rem solid #00A1E2; |
||||||
|
list-style-type: none; |
||||||
|
padding-left: 0; |
||||||
|
} |
||||||
|
|
||||||
|
</style> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
|
||||||
|
<div class="banner lead"> |
||||||
|
Your new Cloud-Native application is ready! |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="container"> |
||||||
|
<div class="left-column"> |
||||||
|
<p class="lead"> Congratulations, you have created a new Quarkus application.</p> |
||||||
|
|
||||||
|
<h2>Why do you see this?</h2> |
||||||
|
|
||||||
|
<p>This page is served by Quarkus. The source is in |
||||||
|
<code>src/main/resources/META-INF/resources/index.html</code>.</p> |
||||||
|
|
||||||
|
<h2>What can I do from here?</h2> |
||||||
|
|
||||||
|
<p>If not already done, run the application in <em>dev mode</em> using: <code>mvn quarkus:dev</code>. |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li>Add REST resources, Servlets, functions and other services in <code>src/main/java</code>.</li> |
||||||
|
<li>Your static assets are located in <code>src/main/resources/META-INF/resources</code>.</li> |
||||||
|
<li>Configure your application in <code>src/main/resources/application.properties</code>. |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
<h2>How do I get rid of this page?</h2> |
||||||
|
<p>Just delete the <code>src/main/resources/META-INF/resources/index.html</code> file.</p> |
||||||
|
</div> |
||||||
|
<div class="right-column"> |
||||||
|
<div class="right-section"> |
||||||
|
<h3>Application</h3> |
||||||
|
<ul> |
||||||
|
<li>GroupId: org.acme</li> |
||||||
|
<li>ArtifactId: getting-started</li> |
||||||
|
<li>Version: 1.0.0-SNAPSHOT</li> |
||||||
|
<li>Quarkus Version: 0.11.0</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div class="right-section"> |
||||||
|
<h3>Next steps</h3> |
||||||
|
<ul> |
||||||
|
<li><a href="https://quarkus.io/guides/maven-tooling.html">Setup your IDE</a></li> |
||||||
|
<li><a href="https://quarkus.io/guides/getting-started-guide.html">Getting started</a></li> |
||||||
|
<li><a href="https://quarkus.io">Quarkus Web Site</a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,11 @@ |
|||||||
|
quarkus.http.port=22800 |
||||||
|
#quarkus.log.level=DEBUG |
||||||
|
quarkus.log.file.encoding=UTF-8 |
||||||
|
|
||||||
|
# 打包成jar时附带依赖 |
||||||
|
quarkus.package.type=uber-jar |
||||||
|
|
||||||
|
# 原生镜像编译附加参数,去掉后编译会失败 |
||||||
|
# 但也只是能编译完成,目前的编译产物完全不可用,有非常多的严重bug |
||||||
|
# 现阶段使用jar运行,启动效率虽不如原生程序,但速度尚可 |
||||||
|
quarkus.native.additional-build-args="--initialize-at-run-time=cn.wustlinghang.mywust" |
@ -1,59 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<groupId>cn.wustlinghang.wusthelper</groupId> |
|
||||||
<artifactId>physics</artifactId> |
|
||||||
<version>0.0.1-SNAPSHOT</version> |
|
||||||
<dependencies> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang</groupId> |
|
||||||
<artifactId>mywust-core</artifactId> |
|
||||||
<version>0.0.2-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang</groupId> |
|
||||||
<artifactId>mywust-network-okhttp</artifactId> |
|
||||||
<version>0.0.2-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>cn.wustlinghang.wusthelper</groupId> |
|
||||||
<artifactId>common</artifactId> |
|
||||||
<version>0.0.1-SNAPSHOT</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>jakarta.annotation</groupId> |
|
||||||
<artifactId>jakarta.annotation-api</artifactId> |
|
||||||
<version>2.1.1</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>javax.annotation</groupId> |
|
||||||
<artifactId>javax.annotation-api</artifactId> |
|
||||||
<version>1.3.2</version> |
|
||||||
<scope>compile</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.projectlombok</groupId> |
|
||||||
<artifactId>lombok</artifactId> |
|
||||||
<version>1.18.26</version> |
|
||||||
<scope>provided</scope> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
<repositories> |
|
||||||
<repository> |
|
||||||
<id>central</id> |
|
||||||
<url>https://repo1.maven.org/maven2</url> |
|
||||||
</repository> |
|
||||||
<repository> |
|
||||||
<snapshots> |
|
||||||
<enabled>true</enabled> |
|
||||||
</snapshots> |
|
||||||
<id>github</id> |
|
||||||
<url>https://maven.pkg.github.com/LingHangStudio/mywust</url> |
|
||||||
</repository> |
|
||||||
</repositories> |
|
||||||
</project> |
|
@ -0,0 +1,54 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/getting-started-jvm . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started-jvm |
||||||
|
# |
||||||
|
# If you want to include the debug port into your docker image |
||||||
|
# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 |
||||||
|
# |
||||||
|
# Then run the container using : |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/getting-started-jvm |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
|
||||||
|
ARG JAVA_PACKAGE=java-11-openjdk-headless |
||||||
|
ARG RUN_JAVA_VERSION=1.3.8 |
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' |
||||||
|
# Install java and the run-java script |
||||||
|
# Also set up permissions for user `1001` |
||||||
|
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ |
||||||
|
&& microdnf update \ |
||||||
|
&& microdnf clean all \ |
||||||
|
&& mkdir /deployments \ |
||||||
|
&& chown 1001 /deployments \ |
||||||
|
&& chmod "g+rwX" /deployments \ |
||||||
|
&& chown 1001:root /deployments \ |
||||||
|
&& curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ |
||||||
|
&& chown 1001 /deployments/run-java.sh \ |
||||||
|
&& chmod 540 /deployments/run-java.sh \ |
||||||
|
&& echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security |
||||||
|
|
||||||
|
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. |
||||||
|
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" |
||||||
|
# We make four distinct layers so if there are application changes the library layers can be re-used |
||||||
|
COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ |
||||||
|
COPY --chown=1001 target/quarkus-app/*.jar /deployments/ |
||||||
|
COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ |
||||||
|
COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
ENTRYPOINT [ "/deployments/run-java.sh" ] |
@ -0,0 +1,51 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Dquarkus.package.type=legacy-jar |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/getting-started-legacy-jar . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started-legacy-jar |
||||||
|
# |
||||||
|
# If you want to include the debug port into your docker image |
||||||
|
# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 |
||||||
|
# |
||||||
|
# Then run the container using : |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/getting-started-legacy-jar |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
|
||||||
|
ARG JAVA_PACKAGE=java-11-openjdk-headless |
||||||
|
ARG RUN_JAVA_VERSION=1.3.8 |
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' |
||||||
|
# Install java and the run-java script |
||||||
|
# Also set up permissions for user `1001` |
||||||
|
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ |
||||||
|
&& microdnf update \ |
||||||
|
&& microdnf clean all \ |
||||||
|
&& mkdir /deployments \ |
||||||
|
&& chown 1001 /deployments \ |
||||||
|
&& chmod "g+rwX" /deployments \ |
||||||
|
&& chown 1001:root /deployments \ |
||||||
|
&& curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ |
||||||
|
&& chown 1001 /deployments/run-java.sh \ |
||||||
|
&& chmod 540 /deployments/run-java.sh \ |
||||||
|
&& echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security |
||||||
|
|
||||||
|
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. |
||||||
|
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" |
||||||
|
COPY target/lib/* /deployments/lib/ |
||||||
|
COPY target/*-runner.jar /deployments/app.jar |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
ENTRYPOINT [ "/deployments/run-java.sh" ] |
@ -0,0 +1,27 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Pnative |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.native -t quarkus/getting-started . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started |
||||||
|
# |
||||||
|
### |
||||||
|
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 |
||||||
|
WORKDIR /work/ |
||||||
|
RUN chown 1001 /work \ |
||||||
|
&& chmod "g+rwX" /work \ |
||||||
|
&& chown 1001:root /work |
||||||
|
COPY --chown=1001:root target/*-runner /work/application |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] |
@ -0,0 +1,23 @@ |
|||||||
|
#### |
||||||
|
# This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode |
||||||
|
# |
||||||
|
# Before building the container image run: |
||||||
|
# |
||||||
|
# ./mvnw package -Pnative |
||||||
|
# |
||||||
|
# Then, build the image with: |
||||||
|
# |
||||||
|
# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/getting-started . |
||||||
|
# |
||||||
|
# Then run the container using: |
||||||
|
# |
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/getting-started |
||||||
|
# |
||||||
|
### |
||||||
|
FROM quay.io/quarkus/quarkus-micro-image:1.0 |
||||||
|
COPY target/*-runner /application |
||||||
|
|
||||||
|
EXPOSE 8080 |
||||||
|
USER 1001 |
||||||
|
|
||||||
|
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] |
@ -1,7 +0,0 @@ |
|||||||
package cn.wustlinghang; |
|
||||||
|
|
||||||
public class Main { |
|
||||||
public static void main(String[] args) { |
|
||||||
System.out.println("Hello world!"); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,32 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.wusthelper.internal.physics.services.LoginService; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/cookie") |
||||||
|
public class CookieApi { |
||||||
|
private final LoginService loginService; |
||||||
|
|
||||||
|
public CookieApi(LoginService loginService) { |
||||||
|
this.loginService = loginService; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String login(@QueryParam("username") @NotNull String username, |
||||||
|
@QueryParam("password") @NotNull String password) throws IOException, ApiException { |
||||||
|
return loginService.login(username, password, false); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/verify") |
||||||
|
public Boolean verify(@QueryParam("cookie") @NotNull String cookie) throws IOException { |
||||||
|
return loginService.verify(cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradCourseTableParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradCourseTableApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.Course; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@Path("/course_table") |
||||||
|
@ApplicationScoped |
||||||
|
public class CourseTableApi { |
||||||
|
private final UndergradCourseTableApiService studentInfoApiService; |
||||||
|
private final UndergradCourseTableParser studentInfoPageParser; |
||||||
|
|
||||||
|
public CourseTableApi(UndergradCourseTableApiService studentInfoApiService, |
||||||
|
UndergradCourseTableParser studentInfoPageParser) { |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public List<Course> get(@QueryParam("cookie") @NotNull String cookie, @QueryParam("term") String term) |
||||||
|
throws IOException, ApiException, ParseException { |
||||||
|
String html = studentInfoApiService.getPage(term, cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie, @QueryParam("term") String term) |
||||||
|
throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public List<Course> parse(String html) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradCreditStatusParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradCreditStatusApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/credit_status") |
||||||
|
@ApplicationScoped |
||||||
|
public class CreditStatusApi { |
||||||
|
private final UndergradCreditStatusApiService creditStatusApiService; |
||||||
|
private final UndergradCreditStatusParser creditStatusParser; |
||||||
|
|
||||||
|
private final RequestClientOption option; |
||||||
|
|
||||||
|
public CreditStatusApi(UndergradCreditStatusApiService creditStatusApiService, |
||||||
|
UndergradCreditStatusParser creditStatusParser, |
||||||
|
RequestClientOption option) { |
||||||
|
this.creditStatusApiService = creditStatusApiService; |
||||||
|
this.creditStatusParser = creditStatusParser; |
||||||
|
this.option = option; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = creditStatusApiService.getPage(cookie, option, false); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return creditStatusApiService.getPage(cookie, option, false); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public String parse(String html) throws ParseException { |
||||||
|
return creditStatusParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradScoreParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradScoreApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.Score; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@Path("/score") |
||||||
|
@ApplicationScoped |
||||||
|
public class ScoreApi { |
||||||
|
private final UndergradScoreApiService scoreApiService; |
||||||
|
private final UndergradScoreParser scoreParser; |
||||||
|
|
||||||
|
public ScoreApi(UndergradScoreApiService scoreApiService, UndergradScoreParser scoreParser) { |
||||||
|
this.scoreApiService = scoreApiService; |
||||||
|
this.scoreParser = scoreParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public List<Score> get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = scoreApiService.getPage(cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return scoreApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public List<Score> parse(String html) throws ParseException { |
||||||
|
return scoreParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradStudentInfoPageParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradStudentInfoApiService; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/student_info") |
||||||
|
@ApplicationScoped |
||||||
|
public class StudentInfoApi { |
||||||
|
private final UndergradStudentInfoApiService studentInfoApiService; |
||||||
|
private final UndergradStudentInfoPageParser studentInfoPageParser; |
||||||
|
|
||||||
|
public StudentInfoApi(UndergradStudentInfoApiService studentInfoApiService, |
||||||
|
UndergradStudentInfoPageParser studentInfoPageParser) { |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public StudentInfo get(@QueryParam("cookie") @NotNull String cookie) throws IOException, ApiException, ParseException { |
||||||
|
return this.parse(this.agent(cookie)); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public StudentInfo parse(String html) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradTrainingPlanPageParser; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradTrainingPlanApiService; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.validation.constraints.NotNull; |
||||||
|
import jakarta.ws.rs.GET; |
||||||
|
import jakarta.ws.rs.POST; |
||||||
|
import jakarta.ws.rs.Path; |
||||||
|
import jakarta.ws.rs.QueryParam; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Path("/training_plan") |
||||||
|
@ApplicationScoped |
||||||
|
public class TrainingPlanApi { |
||||||
|
private final UndergradTrainingPlanApiService trainingPlanApiService; |
||||||
|
private final UndergradTrainingPlanPageParser trainingPlanPageParser; |
||||||
|
|
||||||
|
public TrainingPlanApi(UndergradTrainingPlanApiService trainingPlanApiService, |
||||||
|
UndergradTrainingPlanPageParser trainingPlanPageParser) { |
||||||
|
this.trainingPlanApiService = trainingPlanApiService; |
||||||
|
this.trainingPlanPageParser = trainingPlanPageParser; |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/") |
||||||
|
public String get(String cookie) throws IOException, ApiException, ParseException { |
||||||
|
String html = trainingPlanApiService.getPage(cookie); |
||||||
|
return this.parse(html); |
||||||
|
} |
||||||
|
|
||||||
|
@GET |
||||||
|
@Path("/agent") |
||||||
|
public String agent(@QueryParam("cookie") @NotNull String cookie) |
||||||
|
throws IOException, ApiException { |
||||||
|
return trainingPlanApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
@POST |
||||||
|
@Path("/parse") |
||||||
|
public String parse(String html) throws ParseException { |
||||||
|
return trainingPlanPageParser.parse(html); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
|
||||||
|
@Provider |
||||||
|
public class ApiExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<ApiException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ApiException e) { |
||||||
|
return super.toResponse(e.getCodeValue(), e.toString(), "ApiExceptionHandler"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class DefaultExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<Exception> { |
||||||
|
@Override |
||||||
|
public Response toResponse(Exception e) { |
||||||
|
log.error("未知异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"DefaultExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.ws.rs.core.MediaType; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
|
||||||
|
public abstract class ExceptionHandlerBase { |
||||||
|
public static final String EXCEPTION_HEADER_KEY = "X-exception-handler"; |
||||||
|
|
||||||
|
private static final ObjectMapper objectMapper = new ObjectMapper(); |
||||||
|
|
||||||
|
public Response toResponse(ResponseCode code, String msg, String handlerName) { |
||||||
|
return toResponse(code.getCode(), msg, handlerName); |
||||||
|
} |
||||||
|
|
||||||
|
public Response toResponse(int code, String msg, String handlerName) { |
||||||
|
Object response; |
||||||
|
try { |
||||||
|
response = objectMapper.writeValueAsString(RpcResponse.error(code, msg)); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
response = RpcResponse.error(ResponseCode.SERVER_INTERNAL_ERROR); |
||||||
|
} |
||||||
|
|
||||||
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR) |
||||||
|
.entity(response) |
||||||
|
.header(EXCEPTION_HEADER_KEY, handlerName) |
||||||
|
.type(MediaType.APPLICATION_JSON) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class IOExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<IOException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(IOException e) { |
||||||
|
log.error("IO异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"IOExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class ParseExceptionHandler extends ExceptionHandlerBase implements ExceptionMapper<ParseException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ParseException e) { |
||||||
|
log.error("解析异常:", e); |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.SERVER_INTERNAL_ERROR, |
||||||
|
e.toString(), |
||||||
|
"ParseExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json.handler; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.ResponseCode; |
||||||
|
import jakarta.validation.ValidationException; |
||||||
|
import jakarta.ws.rs.core.Response; |
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Provider |
||||||
|
public class ValidationExceptionHandler extends ExceptionHandlerBase |
||||||
|
implements ExceptionMapper<ValidationException> { |
||||||
|
@Override |
||||||
|
public Response toResponse(ValidationException e) { |
||||||
|
return super.toResponse( |
||||||
|
ResponseCode.PARAM_WRONG, |
||||||
|
"参数错误:" + e.toString(), |
||||||
|
"ValidationExceptionHandler" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.api.json.interceptor; |
||||||
|
|
||||||
|
import cn.wustlinghang.wusthelper.internal.physics.api.json.handler.ExceptionHandlerBase; |
||||||
|
import cn.wustlinghang.wusthelper.rpc.response.RpcResponse; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.ws.rs.WebApplicationException; |
||||||
|
import jakarta.ws.rs.core.HttpHeaders; |
||||||
|
import jakarta.ws.rs.core.MediaType; |
||||||
|
import jakarta.ws.rs.ext.Provider; |
||||||
|
import jakarta.ws.rs.ext.WriterInterceptor; |
||||||
|
import jakarta.ws.rs.ext.WriterInterceptorContext; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@Provider |
||||||
|
public class ResponseWrapperInterceptor implements WriterInterceptor { |
||||||
|
private final ObjectMapper objectMapper; |
||||||
|
|
||||||
|
public ResponseWrapperInterceptor(ObjectMapper objectMapper) { |
||||||
|
this.objectMapper = objectMapper; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { |
||||||
|
boolean hasException = context.getHeaders().get(ExceptionHandlerBase.EXCEPTION_HEADER_KEY) != null; |
||||||
|
if (!hasException) { |
||||||
|
Object data = context.getEntity(); |
||||||
|
RpcResponse<Object> wrappedResponse = RpcResponse.success(data); |
||||||
|
String json = objectMapper.writeValueAsString(wrappedResponse); |
||||||
|
context.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); |
||||||
|
context.setEntity(json); |
||||||
|
} |
||||||
|
|
||||||
|
context.proceed(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.bean; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
import jakarta.inject.Singleton; |
||||||
|
|
||||||
|
public class JacksonBean { |
||||||
|
@ApplicationScoped |
||||||
|
public ObjectMapper objectMapper() { |
||||||
|
return new ObjectMapper(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.bean; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.*; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
public class MywustParserBeans { |
||||||
|
@ApplicationScoped |
||||||
|
public UndergradCourseTableParser undergradCourseTableParser() { |
||||||
|
return new UndergradCourseTableParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradScoreParser undergradScoreParser() { |
||||||
|
return new UndergradScoreParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradStudentInfoPageParser undergradStudentInfoPageParser() { |
||||||
|
return new UndergradStudentInfoPageParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradTrainingPlanPageParser undergradTrainingPlanPageParser() { |
||||||
|
return new UndergradTrainingPlanPageParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradCreditStatusParser undergradCreditStatusParser() { |
||||||
|
return new UndergradCreditStatusParser(); |
||||||
|
} |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public UndergradExamDelayParser undergradExamDelayParser() { |
||||||
|
return new UndergradExamDelayParser(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.bean; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.auth.UndergraduateLogin; |
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import cn.wustlinghang.mywust.network.Requester; |
||||||
|
import cn.wustlinghang.mywust.network.okhttp.SimpleOkhttpRequester; |
||||||
|
import jakarta.inject.Singleton; |
||||||
|
|
||||||
|
public class MywustRequestAgentBeans { |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public RequestClientOption requestClientOption() { |
||||||
|
RequestClientOption.Proxy proxy = RequestClientOption.Proxy.builder() |
||||||
|
.address("127.0.0.1") |
||||||
|
.port(8080) |
||||||
|
.build(); |
||||||
|
RequestClientOption option = new RequestClientOption(); |
||||||
|
// option.setProxy(proxy);
|
||||||
|
|
||||||
|
return option; |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public Requester requester(RequestClientOption option) { |
||||||
|
return new SimpleOkhttpRequester(option, true); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergraduateLogin undergraduateLogin(Requester requester) { |
||||||
|
return new UndergraduateLogin(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradCourseTableApiService undergradCourseTableApiService(Requester requester) { |
||||||
|
return new UndergradCourseTableApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradScoreApiService undergradScoreApiService(Requester requester) { |
||||||
|
return new UndergradScoreApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradStudentInfoApiService undergradStudentInfoApiService(Requester requester) { |
||||||
|
return new UndergradStudentInfoApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradTrainingPlanApiService undergradTrainingPlanApiService(Requester requester) { |
||||||
|
return new UndergradTrainingPlanApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradCreditStatusApiService undergradCreditStatusApiService(Requester requester) { |
||||||
|
return new UndergradCreditStatusApiService(requester); |
||||||
|
} |
||||||
|
|
||||||
|
@Singleton |
||||||
|
public UndergradExamDelayApiService undergradExamDelayApiService(Requester requester) { |
||||||
|
return new UndergradExamDelayApiService(requester); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.auth.UndergraduateLogin; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import cn.wustlinghang.mywust.network.RequestClientOption; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class LoginService { |
||||||
|
private final RequestClientOption option; |
||||||
|
private final UndergraduateLogin undergraduateLogin; |
||||||
|
|
||||||
|
public LoginService(RequestClientOption option, |
||||||
|
UndergraduateLogin undergraduateLogin) { |
||||||
|
this.option = option; |
||||||
|
this.undergraduateLogin = undergraduateLogin; |
||||||
|
} |
||||||
|
|
||||||
|
public String login(String username, String password, boolean legacy) throws IOException, ApiException { |
||||||
|
if (legacy) { |
||||||
|
return undergraduateLogin.getLoginCookieLegacy(username, password, option); |
||||||
|
} else { |
||||||
|
return undergraduateLogin.getLoginCookie(username, password, option); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean verify(String cookie) throws IOException { |
||||||
|
return !undergraduateLogin.checkCookiesFail(cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.parser.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.data.global.Course; |
||||||
|
import cn.wustlinghang.mywust.data.global.Score; |
||||||
|
import cn.wustlinghang.mywust.data.global.StudentInfo; |
||||||
|
import cn.wustlinghang.mywust.data.undergrad.ExamDelayApplication; |
||||||
|
import cn.wustlinghang.mywust.exception.ParseException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class ParseService { |
||||||
|
private final UndergradCourseTableParser courseTableParser; |
||||||
|
private final UndergradScoreParser scoreParser; |
||||||
|
private final UndergradStudentInfoPageParser studentInfoPageParser; |
||||||
|
private final UndergradTrainingPlanPageParser trainingPlanPageParser; |
||||||
|
private final UndergradCreditStatusParser creditStatusParser; |
||||||
|
private final UndergradExamDelayParser examDelayParser; |
||||||
|
|
||||||
|
public ParseService(UndergradCourseTableParser courseTableParser, |
||||||
|
UndergradScoreParser scoreParser, |
||||||
|
UndergradStudentInfoPageParser studentInfoPageParser, |
||||||
|
UndergradTrainingPlanPageParser trainingPlanPageParser, |
||||||
|
UndergradCreditStatusParser creditStatusParser, |
||||||
|
UndergradExamDelayParser examDelayParser) { |
||||||
|
|
||||||
|
this.courseTableParser = courseTableParser; |
||||||
|
this.scoreParser = scoreParser; |
||||||
|
this.studentInfoPageParser = studentInfoPageParser; |
||||||
|
this.trainingPlanPageParser = trainingPlanPageParser; |
||||||
|
this.creditStatusParser = creditStatusParser; |
||||||
|
this.examDelayParser = examDelayParser; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Course> parseCourseTable(String data) throws ParseException { |
||||||
|
return courseTableParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Score> parseScore(String data) throws ParseException { |
||||||
|
return scoreParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public StudentInfo parseStudentInfo(String data) throws ParseException { |
||||||
|
return studentInfoPageParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public String parseTrainingPlan(String data) throws ParseException { |
||||||
|
return trainingPlanPageParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public String parseCreditStatus(String data) throws ParseException { |
||||||
|
return creditStatusParser.parse(data); |
||||||
|
} |
||||||
|
|
||||||
|
public List<ExamDelayApplication> parseExamDelayApplications(String data) throws ParseException { |
||||||
|
return examDelayParser.parse(data); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.physics.services; |
||||||
|
|
||||||
|
import cn.wustlinghang.mywust.core.request.service.undergraduate.*; |
||||||
|
import cn.wustlinghang.mywust.exception.ApiException; |
||||||
|
import jakarta.enterprise.context.ApplicationScoped; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
@ApplicationScoped |
||||||
|
public class RequestAgentService { |
||||||
|
private final UndergradCourseTableApiService courseTableApiService; |
||||||
|
private final UndergradScoreApiService scoreApiService; |
||||||
|
private final UndergradStudentInfoApiService studentInfoApiService; |
||||||
|
private final UndergradTrainingPlanApiService trainingPlanApiService; |
||||||
|
private final UndergradCreditStatusApiService creditStatusApiService; |
||||||
|
private final UndergradExamDelayApiService examDelayApiService; |
||||||
|
|
||||||
|
public RequestAgentService(UndergradCourseTableApiService courseTableApiService, |
||||||
|
UndergradScoreApiService scoreApiService, |
||||||
|
UndergradStudentInfoApiService studentInfoApiService, |
||||||
|
UndergradTrainingPlanApiService trainingPlanApiService, |
||||||
|
UndergradCreditStatusApiService creditStatusApiService, |
||||||
|
UndergradExamDelayApiService examDelayApiService) { |
||||||
|
|
||||||
|
this.courseTableApiService = courseTableApiService; |
||||||
|
this.scoreApiService = scoreApiService; |
||||||
|
this.studentInfoApiService = studentInfoApiService; |
||||||
|
this.trainingPlanApiService = trainingPlanApiService; |
||||||
|
this.creditStatusApiService = creditStatusApiService; |
||||||
|
this.examDelayApiService = examDelayApiService; |
||||||
|
} |
||||||
|
|
||||||
|
public String getStudentInfoPage(String cookie) throws IOException, ApiException { |
||||||
|
return studentInfoApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCourseTable(String cookie, String term) throws IOException, ApiException { |
||||||
|
return courseTableApiService.getPage(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getScore(String cookie) throws IOException, ApiException { |
||||||
|
return scoreApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getTrainingPlan(String cookie) throws IOException, ApiException { |
||||||
|
return trainingPlanApiService.getPage(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCreditStatus(String cookie) throws IOException, ApiException { |
||||||
|
return creditStatusApiService.getPage(cookie, null, false); |
||||||
|
} |
||||||
|
|
||||||
|
public UndergradExamDelayApiService.ExamActivity[] getExamActivities(String cookie, String term) |
||||||
|
throws IOException, ApiException { |
||||||
|
return examDelayApiService.getActivities(term, cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public String getExamDelayApplications(String cookie, String term, String activityId) |
||||||
|
throws IOException, ApiException { |
||||||
|
return examDelayApiService.getPage(term, activityId, cookie); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,152 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<title>getting-started - 1.0.0-SNAPSHOT</title> |
||||||
|
<style> |
||||||
|
h1, h2, h3, h4, h5, h6 { |
||||||
|
margin-bottom: 0.5rem; |
||||||
|
font-weight: 400; |
||||||
|
line-height: 1.5; |
||||||
|
} |
||||||
|
|
||||||
|
h1 { |
||||||
|
font-size: 2.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
h2 { |
||||||
|
font-size: 2rem |
||||||
|
} |
||||||
|
|
||||||
|
h3 { |
||||||
|
font-size: 1.75rem |
||||||
|
} |
||||||
|
|
||||||
|
h4 { |
||||||
|
font-size: 1.5rem |
||||||
|
} |
||||||
|
|
||||||
|
h5 { |
||||||
|
font-size: 1.25rem |
||||||
|
} |
||||||
|
|
||||||
|
h6 { |
||||||
|
font-size: 1rem |
||||||
|
} |
||||||
|
|
||||||
|
.lead { |
||||||
|
font-weight: 300; |
||||||
|
font-size: 2rem; |
||||||
|
} |
||||||
|
|
||||||
|
.banner { |
||||||
|
font-size: 2.7rem; |
||||||
|
margin: 0; |
||||||
|
padding: 2rem 1rem; |
||||||
|
background-color: #00A1E2; |
||||||
|
color: white; |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
margin: 0; |
||||||
|
font-family: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; |
||||||
|
} |
||||||
|
|
||||||
|
code { |
||||||
|
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; |
||||||
|
font-size: 87.5%; |
||||||
|
color: #e83e8c; |
||||||
|
word-break: break-word; |
||||||
|
} |
||||||
|
|
||||||
|
.left-column { |
||||||
|
padding: .75rem; |
||||||
|
max-width: 75%; |
||||||
|
min-width: 55%; |
||||||
|
} |
||||||
|
|
||||||
|
.right-column { |
||||||
|
padding: .75rem; |
||||||
|
max-width: 25%; |
||||||
|
} |
||||||
|
|
||||||
|
.container { |
||||||
|
display: flex; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
li { |
||||||
|
margin: 0.75rem; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section { |
||||||
|
margin-left: 1rem; |
||||||
|
padding-left: 0.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section h3 { |
||||||
|
padding-top: 0; |
||||||
|
font-weight: 200; |
||||||
|
} |
||||||
|
|
||||||
|
.right-section ul { |
||||||
|
border-left: 0.3rem solid #00A1E2; |
||||||
|
list-style-type: none; |
||||||
|
padding-left: 0; |
||||||
|
} |
||||||
|
|
||||||
|
</style> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
|
||||||
|
<div class="banner lead"> |
||||||
|
Your new Cloud-Native application is ready! |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="container"> |
||||||
|
<div class="left-column"> |
||||||
|
<p class="lead"> Congratulations, you have created a new Quarkus application.</p> |
||||||
|
|
||||||
|
<h2>Why do you see this?</h2> |
||||||
|
|
||||||
|
<p>This page is served by Quarkus. The source is in |
||||||
|
<code>src/main/resources/META-INF/resources/index.html</code>.</p> |
||||||
|
|
||||||
|
<h2>What can I do from here?</h2> |
||||||
|
|
||||||
|
<p>If not already done, run the application in <em>dev mode</em> using: <code>mvn quarkus:dev</code>. |
||||||
|
</p> |
||||||
|
<ul> |
||||||
|
<li>Add REST resources, Servlets, functions and other services in <code>src/main/java</code>.</li> |
||||||
|
<li>Your static assets are located in <code>src/main/resources/META-INF/resources</code>.</li> |
||||||
|
<li>Configure your application in <code>src/main/resources/application.properties</code>. |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
<h2>How do I get rid of this page?</h2> |
||||||
|
<p>Just delete the <code>src/main/resources/META-INF/resources/index.html</code> file.</p> |
||||||
|
</div> |
||||||
|
<div class="right-column"> |
||||||
|
<div class="right-section"> |
||||||
|
<h3>Application</h3> |
||||||
|
<ul> |
||||||
|
<li>GroupId: org.acme</li> |
||||||
|
<li>ArtifactId: getting-started</li> |
||||||
|
<li>Version: 1.0.0-SNAPSHOT</li> |
||||||
|
<li>Quarkus Version: 0.11.0</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div class="right-section"> |
||||||
|
<h3>Next steps</h3> |
||||||
|
<ul> |
||||||
|
<li><a href="https://quarkus.io/guides/maven-tooling.html">Setup your IDE</a></li> |
||||||
|
<li><a href="https://quarkus.io/guides/getting-started-guide.html">Getting started</a></li> |
||||||
|
<li><a href="https://quarkus.io">Quarkus Web Site</a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,11 @@ |
|||||||
|
quarkus.http.port=22800 |
||||||
|
#quarkus.log.level=DEBUG |
||||||
|
quarkus.log.file.encoding=UTF-8 |
||||||
|
|
||||||
|
# 打包成jar时附带依赖 |
||||||
|
quarkus.package.type=uber-jar |
||||||
|
|
||||||
|
# 原生镜像编译附加参数,去掉后编译会失败 |
||||||
|
# 但也只是能编译完成,目前的编译产物完全不可用,有非常多的严重bug |
||||||
|
# 现阶段使用jar运行,启动效率虽不如原生程序,但速度尚可 |
||||||
|
quarkus.native.additional-build-args="--initialize-at-run-time=cn.wustlinghang.mywust" |
@ -0,0 +1,16 @@ |
|||||||
|
package cn.wustlinghang.wusthelper.internal.undergrad; |
||||||
|
|
||||||
|
import io.quarkus.runtime.Startup; |
||||||
|
import jakarta.annotation.PostConstruct; |
||||||
|
import jakarta.inject.Singleton; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@Startup |
||||||
|
@Singleton |
||||||
|
public class Main { |
||||||
|
@PostConstruct |
||||||
|
public void run() { |
||||||
|
log.info("Undergrad service started."); |
||||||
|
} |
||||||
|
} |
@ -1,4 +0,0 @@ |
|||||||
package cn.wustlinghang.wusthelper.internal.undergrad.exception; |
|
||||||
|
|
||||||
public class InternalException extends Exception { |
|
||||||
} |
|
Loading…
Reference in new issue