diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/Mywust.java b/mywust-core/src/main/java/cn/linghang/mywust/core/Mywust.java deleted file mode 100644 index 4937d46..0000000 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/Mywust.java +++ /dev/null @@ -1,5 +0,0 @@ -package cn.linghang.mywust.core; - -public class Mywust { - -} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/MywustFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/MywustFactory.java deleted file mode 100644 index 773082d..0000000 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/MywustFactory.java +++ /dev/null @@ -1,5 +0,0 @@ -package cn.linghang.mywust.core; - -public class MywustFactory { - -} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/api/Graduate.java b/mywust-core/src/main/java/cn/linghang/mywust/core/api/GraduateUrls.java similarity index 96% rename from mywust-core/src/main/java/cn/linghang/mywust/core/api/Graduate.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/api/GraduateUrls.java index 8b64c05..a99c7c5 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/api/Graduate.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/api/GraduateUrls.java @@ -1,6 +1,6 @@ package cn.linghang.mywust.core.api; -public class Graduate { +public class GraduateUrls { public static final String GRADUATE_CAPTCHA_API = "http://59.68.177.189/pyxx/PageTemplate/NsoftPage/yzm/createyzm.aspx"; public static final String GRADUATE_LOGIN_API = "http://59.68.177.189/pyxx/login.aspx"; diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/api/Library.java b/mywust-core/src/main/java/cn/linghang/mywust/core/api/LibraryUrls.java similarity index 96% rename from mywust-core/src/main/java/cn/linghang/mywust/core/api/Library.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/api/LibraryUrls.java index c55bb29..ec3a1ee 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/api/Library.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/api/LibraryUrls.java @@ -1,6 +1,6 @@ package cn.linghang.mywust.core.api; -public class Library { +public class LibraryUrls { public static final String LIBRARY_SESSION_COOKIE_API = "https://libsys.wust.edu.cn/meta-local/opac/cas/rosetta?ticket=%s"; public static final String LIBRARY_INDEX_URL = "https://libsys.wust.edu.cn/meta-local/opac/cas/rosetta"; diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/api/PhysicsSystem.java b/mywust-core/src/main/java/cn/linghang/mywust/core/api/PhysicsSystemUrls.java similarity index 95% rename from mywust-core/src/main/java/cn/linghang/mywust/core/api/PhysicsSystem.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/api/PhysicsSystemUrls.java index 398084c..4be73c3 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/api/PhysicsSystem.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/api/PhysicsSystemUrls.java @@ -1,6 +1,6 @@ package cn.linghang.mywust.core.api; -public class PhysicsSystem { +public class PhysicsSystemUrls { public static final String PHYSICS_LOGIN_INDEX = "http://wlsy.wust.edu.cn/Page/BI/BI000.aspx"; public static final String PHYSICS_LOGIN_COOKIES_API = "http://wlsy.wust.edu.cn/Page/BI/BI000.aspx"; diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/api/Bkjx.java b/mywust-core/src/main/java/cn/linghang/mywust/core/api/UndergradUrls.java similarity index 97% rename from mywust-core/src/main/java/cn/linghang/mywust/core/api/Bkjx.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/api/UndergradUrls.java index 40ad509..d42c5fd 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/api/Bkjx.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/api/UndergradUrls.java @@ -7,7 +7,7 @@ import lombok.Getter; *

其实是本科生用的教务处系统

*/ @Getter -public class Bkjx { +public class UndergradUrls { public static final String BKJX_SESSION_COOKIE_API = "http://bkjx.wust.edu.cn/jsxsd/sso.jsp?ticket=%s"; public static final String BKJX_TEST_API = "http://bkjx.wust.edu.cn/jsxsd/framework/blankPage.jsp"; diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/api/UnionAuth.java b/mywust-core/src/main/java/cn/linghang/mywust/core/api/UnionAuthUrls.java similarity index 95% rename from mywust-core/src/main/java/cn/linghang/mywust/core/api/UnionAuth.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/api/UnionAuthUrls.java index fdf42cf..ea041b7 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/api/UnionAuth.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/api/UnionAuthUrls.java @@ -1,6 +1,6 @@ package cn.linghang.mywust.core.api; -public class UnionAuth { +public class UnionAuthUrls { /** * 统一认证登录验证的api地址,请求之后可进一步获取service ticket来对具体的服务进行登录获取Cookies */ diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/exception/ApiException.java b/mywust-core/src/main/java/cn/linghang/mywust/core/exception/ApiException.java index ffd197c..b87798f 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/exception/ApiException.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/exception/ApiException.java @@ -12,6 +12,14 @@ public class ApiException extends BasicException { this.code = code; } + public static ApiException create(Code code, String message) { + return new ApiException(code, message); + } + + public static ApiException create(Code code) { + return new ApiException(code); + } + public Code getCode() { return code; } @@ -40,6 +48,11 @@ public class ApiException extends BasicException { */ NETWORK_EXCEPTION(-2, "网络错误..."), + /** + * 输入参数错误 + */ + PARAM_WRONG_EXCEPTION(-3, "输入参数错误..."), + // -------------------------------- // 统一认证的异常(本科生、图书馆) @@ -58,6 +71,33 @@ public class ApiException extends BasicException { */ UNI_LOGIN_USER_BANNED(100102, "统一认证登录: 用户被封禁"), + /** + * 用户账号停用 + */ + UNI_LOGIN_USER_DISABLED(100103, "统一认证登录: 用户已停用"), + + /** + * 用户账号需要更改密码 + */ + UNI_LOGIN_NEED_CHANGE_PASSWORD(100104, "统一认证登录: 用户账号密码需要修改"), + + // 下面的几个几乎不会遇到,但是从官网源码来看是有可能的 + + /** + * 用户账号不唯一 + */ + UNI_LOGIN_USER_NOT_ONLY(100105, "统一认证登录: 用户不唯一,请联系学校处理"), + + /** + * 用户未注册 + */ + UNI_LOGIN_NO_REGISTER(100106, "统一认证登录: 用户未注册"), + + /** + * 用户账号设置了TFA验证,不能直接用密码账号登录 + */ + UNI_LOGIN_NEED_TFA(100107, "统一认证登录: 用户账号需要TFA二步验证"), + // -------------------------------- // 共有异常码:cookie无效 @@ -69,6 +109,11 @@ public class ApiException extends BasicException { // -------------------------------- // 本科生API异常代码 + /** + * + */ + BKJX_LEGACY_LOGIN_PASSWORD_WRONG(110101, "本科教学系统-旧版登录方式:密码错误"), + /** * 需要评教 */ diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/graduate/GraduateExamInfoParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/graduate/GraduateScoreParser.java similarity index 56% rename from mywust-core/src/main/java/cn/linghang/mywust/core/parser/graduate/GraduateExamInfoParser.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/parser/graduate/GraduateScoreParser.java index 586066f..6e1ea32 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/graduate/GraduateExamInfoParser.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/graduate/GraduateScoreParser.java @@ -2,7 +2,7 @@ package cn.linghang.mywust.core.parser.graduate; import cn.linghang.mywust.core.exception.ParseException; import cn.linghang.mywust.core.parser.Parser; -import cn.linghang.mywust.model.global.ExamInfo; +import cn.linghang.mywust.model.global.Score; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -11,13 +11,13 @@ import org.jsoup.select.Elements; import java.util.ArrayList; import java.util.List; -public class GraduateExamInfoParser implements Parser> { +public class GraduateScoreParser implements Parser> { @Override - public List parse(String html) throws ParseException { + public List parse(String html) throws ParseException { Document document = Jsoup.parse(html); Elements scoreElements = document.getElementsByClass("GridViewRowStyle"); - List examInfos = new ArrayList<>(scoreElements.size()); + List scores = new ArrayList<>(scoreElements.size()); for (Element scoreElement : scoreElements) { Elements infoGirds = scoreElement.getElementsByTag("td"); @@ -27,16 +27,16 @@ public class GraduateExamInfoParser implements Parser> { scoreElements.removeIf(element -> element.hasClass("pagestopr")); - ExamInfo examInfo = new ExamInfo(); + Score score = new Score(); - examInfo.setCourseName(infoGirds.get(0).text()); - examInfo.setCredit(infoGirds.get(1).text()); - examInfo.setTerm(infoGirds.get(2).text()); - examInfo.setScore(infoGirds.get(3).text()); + score.setCourseName(infoGirds.get(0).text()); + score.setCredit(infoGirds.get(1).text()); + score.setTerm(infoGirds.get(2).text()); + score.setScore(infoGirds.get(3).text()); - examInfos.add(examInfo); + scores.add(score); } - return examInfos; + return scores; } } diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/ExamInfoParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/ExamInfoParser.java deleted file mode 100644 index 681cadf..0000000 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/ExamInfoParser.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.linghang.mywust.core.parser.undergraduate; - -import cn.linghang.mywust.core.exception.ParseException; -import cn.linghang.mywust.core.parser.Parser; -import cn.linghang.mywust.core.util.JsoupUtil; -import cn.linghang.mywust.model.global.ExamInfo; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -public class ExamInfoParser implements Parser> { - private static final Logger log = LoggerFactory.getLogger(ExamInfoParser.class); - - @Override - public List parse(String html) throws ParseException { - Elements rows = Jsoup.parse(html).selectXpath(ExamInfoXpath.EXAM_INFO_ROWS_XPATH); - if (rows.isEmpty()) { - throw new ParseException(html); - } - - List examInfos = new ArrayList<>(rows.size()); - - try { - for (Element row : rows) { - // 提取出当前行的所有格子 - Elements girds = row.getElementsByTag("td"); - - // 如果这行格子数少于6个,即到了“成绩”的那个格子就没了,那就没啥意义了,直接跳过,不理了 - if (girds.size() < 6) { - continue; - } - - ExamInfo examInfo = new ExamInfo(); - - // 这段看着震撼,但其实很丑 - examInfo.setId(JsoupUtil.getElementContext(girds.get(0))); - - examInfo.setTerm(JsoupUtil.getElementContext(girds.get(1))); - examInfo.setCourseNumber(JsoupUtil.getElementContext(girds.get(2))); - - examInfo.setCourseName(JsoupUtil.getElementContext(girds.get(3))); - examInfo.setGroupName(JsoupUtil.getElementContext(girds.get(4))); - - examInfo.setScore(JsoupUtil.getElementContext(girds.get(5))); - examInfo.setFlag(JsoupUtil.getElementContext(girds.get(6))); - examInfo.setCredit(JsoupUtil.getElementContext(girds.get(7))); - examInfo.setCourseHours(JsoupUtil.getElementContext(girds.get(8))); - examInfo.setGradePoint(JsoupUtil.getElementContext(girds.get(9))); - - examInfo.setEvaluateMethod(JsoupUtil.getElementContext(girds.get(11))); - examInfo.setKind(JsoupUtil.getElementContext(girds.get(12))); - examInfo.setCourseKind(JsoupUtil.getElementContext(girds.get(13))); - - examInfos.add(examInfo); - } - } catch (Exception e) { - log.warn("解析成绩页面时发生错误:{}", e.getMessage()); - log.warn("终止解析,返回已解析数据"); - } - - return examInfos; - } -} - -final class ExamInfoXpath { - public static final String EXAM_INFO_ROWS_XPATH = "//*[@id=\"dataList\"]/tbody/tr"; -} \ No newline at end of file diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/CourseTableParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradCourseTableParser.java similarity index 97% rename from mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/CourseTableParser.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradCourseTableParser.java index ebe7f5f..2865630 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/CourseTableParser.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradCourseTableParser.java @@ -15,8 +15,8 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class CourseTableParser implements Parser> { - private static final Logger log = LoggerFactory.getLogger(CourseTableParser.class); +public class UndergradCourseTableParser implements Parser> { + private static final Logger log = LoggerFactory.getLogger(UndergradCourseTableParser.class); private static final String COURSE_SPLIT_STR = "---------------------"; diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradScoreParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradScoreParser.java new file mode 100644 index 0000000..69a3126 --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradScoreParser.java @@ -0,0 +1,72 @@ +package cn.linghang.mywust.core.parser.undergraduate; + +import cn.linghang.mywust.core.exception.ParseException; +import cn.linghang.mywust.core.parser.Parser; +import cn.linghang.mywust.core.util.JsoupUtil; +import cn.linghang.mywust.model.global.Score; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public class UndergradScoreParser implements Parser> { + private static final Logger log = LoggerFactory.getLogger(UndergradScoreParser.class); + + @Override + public List parse(String html) throws ParseException { + Elements rows = Jsoup.parse(html).selectXpath(UndergradScoreXpath.EXAM_INFO_ROWS_XPATH); + if (rows.isEmpty()) { + throw new ParseException(html); + } + + List scores = new ArrayList<>(rows.size()); + + try { + for (Element row : rows) { + // 提取出当前行的所有格子 + Elements girds = row.getElementsByTag("td"); + + // 如果这行格子数少于6个,即到了“成绩”的那个格子就没了,那就没啥意义了,直接跳过,不理了 + if (girds.size() < 6) { + continue; + } + + Score score = new Score(); + + // 这段看着震撼,但其实很丑 + score.setId(JsoupUtil.getElementContext(girds.get(0))); + + score.setTerm(JsoupUtil.getElementContext(girds.get(1))); + score.setCourseNumber(JsoupUtil.getElementContext(girds.get(2))); + + score.setCourseName(JsoupUtil.getElementContext(girds.get(3))); + score.setGroupName(JsoupUtil.getElementContext(girds.get(4))); + + score.setScore(JsoupUtil.getElementContext(girds.get(5))); + score.setFlag(JsoupUtil.getElementContext(girds.get(6))); + score.setCredit(JsoupUtil.getElementContext(girds.get(7))); + score.setCourseHours(JsoupUtil.getElementContext(girds.get(8))); + score.setGradePoint(JsoupUtil.getElementContext(girds.get(9))); + + score.setEvaluateMethod(JsoupUtil.getElementContext(girds.get(11))); + score.setKind(JsoupUtil.getElementContext(girds.get(12))); + score.setCourseKind(JsoupUtil.getElementContext(girds.get(13))); + + scores.add(score); + } + } catch (Exception e) { + log.warn("解析成绩页面时发生错误:{}", e.getMessage()); + log.warn("终止解析,返回已解析数据"); + } + + return scores; + } +} + +final class UndergradScoreXpath { + public static final String EXAM_INFO_ROWS_XPATH = "//*[@id=\"dataList\"]/tbody/tr"; +} \ No newline at end of file diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/StudentInfoPageParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradStudentInfoPageParser.java similarity index 98% rename from mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/StudentInfoPageParser.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradStudentInfoPageParser.java index cc014fd..11dc94e 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/StudentInfoPageParser.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradStudentInfoPageParser.java @@ -8,7 +8,7 @@ import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; -public class StudentInfoPageParser implements Parser { +public class UndergradStudentInfoPageParser implements Parser { public StudentInfo parse(String html) throws ParseException { Document page = Jsoup.parse(html); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/TrainingPlanPageParser.java b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradTrainingPlanPageParser.java similarity index 92% rename from mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/TrainingPlanPageParser.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradTrainingPlanPageParser.java index 77e9f3d..b33ce17 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/TrainingPlanPageParser.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/parser/undergraduate/UndergradTrainingPlanPageParser.java @@ -5,7 +5,7 @@ import cn.linghang.mywust.core.parser.Parser; import org.jsoup.Jsoup; import org.jsoup.select.Elements; -public class TrainingPlanPageParser implements Parser { +public class UndergradTrainingPlanPageParser implements Parser { @Override public String parse(String html) throws ParseException { diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/RequestFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/RequestFactory.java index 00a1d87..c795b23 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/request/RequestFactory.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/RequestFactory.java @@ -3,6 +3,7 @@ package cn.linghang.mywust.core.request; import cn.linghang.mywust.network.entitys.HttpRequest; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.Map; public class RequestFactory { @@ -29,6 +30,23 @@ public class RequestFactory { .addHeaders(DEFAULT_HTTP_REQUEST.getHeaders()); } + public static HttpRequest makeHttpRequest(String url, String data) { + return makeStringDataHttpRequest(url, data, null); + } + + public static HttpRequest makeHttpRequest(String url, String data, String cookies, Map additionalHeaders) { + return makeStringDataHttpRequest(url, data, cookies).addHeaders(additionalHeaders); + } + + public static HttpRequest makeStringDataHttpRequest(String url, String stringData, String cookies) { + return HttpRequest.builder() + .url(makeUrl(url)) + .data(stringData.getBytes(StandardCharsets.UTF_8)) + .cookies(cookies) + .build() + .addHeaders(DEFAULT_HTTP_REQUEST.getHeaders()); + } + public static URL makeUrl(String url) { try { return new URL(url); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/auth/UnionAuthRequestFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/auth/UnionAuthRequestFactory.java index 88b7875..659a25b 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/request/auth/UnionAuthRequestFactory.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/auth/UnionAuthRequestFactory.java @@ -1,6 +1,6 @@ package cn.linghang.mywust.core.request.auth; -import cn.linghang.mywust.core.api.UnionAuth; +import cn.linghang.mywust.core.api.UnionAuthUrls; import cn.linghang.mywust.core.request.RequestFactory; import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.util.StringUtil; @@ -19,7 +19,7 @@ public class UnionAuthRequestFactory extends RequestFactory { String queryString = StringUtil.generateQueryString(requestForm); - return makeHttpRequest(UnionAuth.UNION_AUTH_API, queryString.getBytes(StandardCharsets.UTF_8)); + return makeHttpRequest(UnionAuthUrls.UNION_AUTH_API, queryString.getBytes(StandardCharsets.UTF_8)); } public static HttpRequest loginTicketRequest(String redirectUrl, String service) { diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/graduate/GraduateRequestFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/graduate/GraduateRequestFactory.java index 6101b75..9106d4b 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/request/graduate/GraduateRequestFactory.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/graduate/GraduateRequestFactory.java @@ -1,7 +1,7 @@ package cn.linghang.mywust.core.request.graduate; import cn.linghang.mywust.captcha.SolvedImageCaptcha; -import cn.linghang.mywust.core.api.Graduate; +import cn.linghang.mywust.core.api.GraduateUrls; import cn.linghang.mywust.core.request.RequestFactory; import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.util.StringUtil; @@ -12,7 +12,7 @@ import java.util.Map; public class GraduateRequestFactory extends RequestFactory { public static HttpRequest captchaRequest() { - return makeHttpRequest(Graduate.GRADUATE_CAPTCHA_API); + return makeHttpRequest(GraduateUrls.GRADUATE_CAPTCHA_API); } private static final Map LOGIN_CONST_PARAMS = new HashMap<>(5); @@ -33,22 +33,22 @@ public class GraduateRequestFactory extends RequestFactory { byte[] requestData = StringUtil.generateQueryString(params).getBytes(StandardCharsets.UTF_8); - return makeHttpRequest(Graduate.GRADUATE_LOGIN_API, requestData, captcha.getBindInfo()); + return makeHttpRequest(GraduateUrls.GRADUATE_LOGIN_API, requestData, captcha.getBindInfo()); } public static HttpRequest studentInfoRequest(String cookie) { - return makeHttpRequest(Graduate.GRADUATE_STUDENT_INFO_API, null, cookie); + return makeHttpRequest(GraduateUrls.GRADUATE_STUDENT_INFO_API, null, cookie); } public static HttpRequest courseTableRequest(String cookie) { - return makeHttpRequest(Graduate.GRADUATE_COURSE_TABLE_API, null, cookie); + return makeHttpRequest(GraduateUrls.GRADUATE_COURSE_TABLE_API, null, cookie); } public static HttpRequest examScoreInfoRequest(String cookie) { - return makeHttpRequest(Graduate.GRADUATE_SCORE_API, null, cookie); + return makeHttpRequest(GraduateUrls.GRADUATE_SCORE_API, null, cookie); } public static HttpRequest trainingPlanPageRequest(String cookie) { - return makeHttpRequest(Graduate.GRADUATE_TRAINING_PLAN_PAGE_API, null, cookie); + return makeHttpRequest(GraduateUrls.GRADUATE_TRAINING_PLAN_PAGE_API, null, cookie); } } diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/library/LibraryRequestFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/library/LibraryRequestFactory.java index e0004ec..8b9928c 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/request/library/LibraryRequestFactory.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/library/LibraryRequestFactory.java @@ -1,27 +1,31 @@ package cn.linghang.mywust.core.request.library; -import cn.linghang.mywust.core.api.Library; +import cn.linghang.mywust.core.api.LibraryUrls; import cn.linghang.mywust.core.request.RequestFactory; import cn.linghang.mywust.network.entitys.HttpRequest; public class LibraryRequestFactory extends RequestFactory { public static HttpRequest sessionCookieRequest(String serviceTicket) { - return makeHttpRequest(String.format(Library.LIBRARY_SESSION_COOKIE_API, serviceTicket)); + return makeHttpRequest(String.format(LibraryUrls.LIBRARY_SESSION_COOKIE_API, serviceTicket)); } public static HttpRequest indexRequest() { - return makeHttpRequest(Library.LIBRARY_INDEX_URL); + return makeHttpRequest(LibraryUrls.LIBRARY_INDEX_URL); } public static HttpRequest currentLoanRequest(String cookie) { - return makeHttpRequest(Library.LIBRARY_CURRENT_LOAN_API, null, cookie); + return makeHttpRequest(LibraryUrls.LIBRARY_CURRENT_LOAN_API, null, cookie); } public static HttpRequest loanHistoryRequest(String cookie) { - return makeHttpRequest(Library.LIBRARY_LOAN_HISTORY_API, null, cookie); + return makeHttpRequest(LibraryUrls.LIBRARY_LOAN_HISTORY_API, null, cookie); } public static HttpRequest overdueSoonRequest(String cookie) { - return makeHttpRequest(Library.LIBRARY_OVERDUE_SOON_API, null, cookie); + return makeHttpRequest(LibraryUrls.LIBRARY_OVERDUE_SOON_API, null, cookie); + } + + public static HttpRequest bookInfoRequest(String cookie) { + return makeHttpRequest(LibraryUrls.LIBRARY_OVERDUE_SOON_API, null, cookie); } } diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/physics/PhysicsSystemRequestFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/physics/PhysicsSystemRequestFactory.java index 27c098e..8e1b31e 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/request/physics/PhysicsSystemRequestFactory.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/physics/PhysicsSystemRequestFactory.java @@ -1,6 +1,6 @@ package cn.linghang.mywust.core.request.physics; -import cn.linghang.mywust.core.api.PhysicsSystem; +import cn.linghang.mywust.core.api.PhysicsSystemUrls; import cn.linghang.mywust.core.request.RequestFactory; import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.util.StringUtil; @@ -11,16 +11,16 @@ import java.util.Map; public class PhysicsSystemRequestFactory extends RequestFactory { public static HttpRequest loginIndexRequest() { - return makeHttpRequest(PhysicsSystem.PHYSICS_LOGIN_INDEX); + return makeHttpRequest(PhysicsSystemUrls.PHYSICS_LOGIN_INDEX); } public static HttpRequest loginCookiesRequest(String username, String password, String cookies) { byte[] queryData = StringUtil.generateQueryString(makeLoginQueryParam(username, password)).getBytes(StandardCharsets.UTF_8); - return makeHttpRequest(PhysicsSystem.PHYSICS_LOGIN_COOKIES_API, queryData, cookies); + return makeHttpRequest(PhysicsSystemUrls.PHYSICS_LOGIN_COOKIES_API, queryData, cookies); } public static HttpRequest mainIndexRequest(String cookies) { - return makeHttpRequest(PhysicsSystem.PHYSICS_MAIN_INDEX_URL, null, cookies); + return makeHttpRequest(PhysicsSystemUrls.PHYSICS_MAIN_INDEX_URL, null, cookies); } public static HttpRequest physicsSystemIndexRequest(String redirect, String cookies) { @@ -38,11 +38,11 @@ public class PhysicsSystemRequestFactory extends RequestFactory { indexParam.put("__ASYNCPOST", "true"); byte[] fromData = StringUtil.generateQueryString(indexParam).getBytes(StandardCharsets.UTF_8); - return makeHttpRequest(PhysicsSystem.PHYSICS_COURSE_INDEX_URL, fromData, cookies); + return makeHttpRequest(PhysicsSystemUrls.PHYSICS_COURSE_INDEX_URL, fromData, cookies); } public static HttpRequest physicsCourseRequest(String cookies) { - return makeHttpRequest(PhysicsSystem.PHYSICS_COURSE_API, null, cookies); + return makeHttpRequest(PhysicsSystemUrls.PHYSICS_COURSE_API, null, cookies); } private static Map makeLoginQueryParam(String username, String password) { diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/BkjxRequestFactory.java b/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/BkjxRequestFactory.java index 6479be5..57ec605 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/BkjxRequestFactory.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/request/undergrade/BkjxRequestFactory.java @@ -1,22 +1,23 @@ package cn.linghang.mywust.core.request.undergrade; -import cn.linghang.mywust.core.api.Bkjx; +import cn.linghang.mywust.core.api.UndergradUrls; import cn.linghang.mywust.core.request.RequestFactory; import cn.linghang.mywust.network.entitys.FormBodyBuilder; import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.util.StringUtil; import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.Map; import java.util.TreeMap; public class BkjxRequestFactory extends RequestFactory { public static HttpRequest sessionCookieRequest(String serviceTicket) { - return makeHttpRequest(String.format(Bkjx.BKJX_SESSION_COOKIE_API, serviceTicket)); + return makeHttpRequest(String.format(UndergradUrls.BKJX_SESSION_COOKIE_API, serviceTicket)); } public static HttpRequest studentInfoRequest(String cookies) { - return makeHttpRequest(Bkjx.BKJX_STUDENT_INFO_API, null, cookies); + return makeHttpRequest(UndergradUrls.BKJX_STUDENT_INFO_API, null, cookies); } public static HttpRequest examScoreInfoRequest(String cookies, String time, String courseKind, String courseName) { @@ -34,11 +35,11 @@ public class BkjxRequestFactory extends RequestFactory { formBodyBuilder.add("xsfs", "all"); byte[] postData = formBodyBuilder.buildAndToString().getBytes(StandardCharsets.UTF_8); - return makeHttpRequest(Bkjx.BKJX_EXAM_INFO_API, postData, cookies); + return makeHttpRequest(UndergradUrls.BKJX_EXAM_INFO_API, postData, cookies); } public static HttpRequest trainingPlanPageRequest(String cookies) { - return makeHttpRequest(Bkjx.BKJX_SCHEME_API, null, cookies); + return makeHttpRequest(UndergradUrls.BKJX_SCHEME_API, null, cookies); } public static HttpRequest courseTablePageRequest(String term, String cookies) { @@ -48,6 +49,28 @@ public class BkjxRequestFactory extends RequestFactory { byte[] queryData = StringUtil.generateQueryString(params).getBytes(StandardCharsets.UTF_8); - return makeHttpRequest(Bkjx.BKJX_COURSE_TABLE_API, queryData, cookies); + return makeHttpRequest(UndergradUrls.BKJX_COURSE_TABLE_API, queryData, cookies); + } + + public static class Legacy { + public static HttpRequest dataStringRequest() { + return makeHttpRequest(UndergradUrls.Legacy.BKJX_DATA_STRING_API); + } + + public static HttpRequest ticketRedirectRequest(String encode) { + Map queryParams = new HashMap<>(); + queryParams.put("userAccount", ""); + queryParams.put("userPassword", ""); + queryParams.put("encoded", encode); + + String queryString = StringUtil.generateQueryString(queryParams); + + Map extendHeaders = new HashMap<>(); + extendHeaders.put("Referer", "http://bkjx.wust.edu.cn/"); + extendHeaders.put("Origin", "http://bkjx.wust.edu.cn"); + + return makeHttpRequest(UndergradUrls.Legacy.BKJX_SESSION_COOKIE_API, queryString.getBytes(StandardCharsets.UTF_8)) + .addHeaders(extendHeaders); + } } } diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/GraduateLogin.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/GraduateLogin.java index d7fbf30..3641c4e 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/GraduateLogin.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/GraduateLogin.java @@ -2,7 +2,9 @@ package cn.linghang.mywust.core.service.auth; import cn.linghang.mywust.captcha.SolvedImageCaptcha; import cn.linghang.mywust.captcha.UnsolvedImageCaptcha; +import cn.linghang.mywust.core.api.GraduateUrls; import cn.linghang.mywust.core.exception.ApiException; +import cn.linghang.mywust.core.request.RequestFactory; import cn.linghang.mywust.core.request.graduate.GraduateRequestFactory; import cn.linghang.mywust.core.service.captcha.solver.CaptchaSolver; import cn.linghang.mywust.network.RequestClientOption; @@ -53,6 +55,23 @@ public class GraduateLogin { // 使用当初通过验证码得到的cookie来作为登录cookie,至于是否真正可行待验证 return captchaImageResponse.getCookies(); } + + public void checkCookies(String cookie, RequestClientOption option) throws ApiException, IOException { + HttpRequest request = RequestFactory.makeHttpRequest(GraduateUrls.GRADUATE_INDEX_TEST_API, null, cookie); + HttpResponse response = requester.get(request, option); + + this.checkResponse(response); + } + + public void checkResponse(HttpResponse response) throws ApiException { + // 检查响应是否正确 + if (response.getBody() == null || + response.getStatusCode() != HttpResponse.HTTP_OK || + new String(response.getBody()).contains("name=\"_ctl0:txtpassword\"")) { + + throw new ApiException(ApiException.Code.COOKIE_INVALID); + } + } } class ImageUtil { diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/JwcLogin.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/JwcLogin.java deleted file mode 100644 index 1c3a95b..0000000 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/JwcLogin.java +++ /dev/null @@ -1,62 +0,0 @@ -package cn.linghang.mywust.core.service.auth; - -import cn.linghang.mywust.core.api.Bkjx; -import cn.linghang.mywust.core.api.UnionAuth; -import cn.linghang.mywust.core.exception.ApiException; -import cn.linghang.mywust.core.exception.BasicException; -import cn.linghang.mywust.core.request.undergrade.BkjxRequestFactory; -import cn.linghang.mywust.network.RequestClientOption; -import cn.linghang.mywust.network.Requester; -import cn.linghang.mywust.network.entitys.HttpRequest; -import cn.linghang.mywust.network.entitys.HttpResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; - -public class JwcLogin { - private static final Logger log = LoggerFactory.getLogger(JwcLogin.class); - - private final Requester requester; - - private final UnionLogin unionLogin; - - public JwcLogin(Requester requester) { - this.requester = requester; - this.unionLogin = new UnionLogin(requester); - } - - public String getLoginCookie(String username, String password, RequestClientOption requestOption) throws IOException, ApiException { - // 获取service ticket以进行进一步的登录 - String serviceTicket = unionLogin.getServiceTicket(username, password, UnionAuth.Service.BKJX_SSO_SERVICE, requestOption); - - // 获取登录cookie(session) - HttpRequest sessionRequest = BkjxRequestFactory.sessionCookieRequest(serviceTicket); - HttpResponse sessionResponse = requester.get(sessionRequest, requestOption); - - String cookies = sessionResponse.getCookies(); - if (roughCheckCookie(cookies)) { - throw new ApiException(ApiException.Code.UNKNOWN_EXCEPTION); - } - - return cookies; - } - - private boolean roughCheckCookie(String cookies) { - return cookies == null || !cookies.contains("JSESSIONID") || !cookies.contains("SERVERID"); - } - - private static final int COOKIES_ERROR_RESPONSE_LENGTH = - ("") - .length(); - - public boolean checkCookies(String cookies, RequestClientOption option) throws IOException { - HttpRequest testRequest = BkjxRequestFactory.makeHttpRequest(Bkjx.BKJX_TEST_API, null, cookies); - HttpResponse testResponse = requester.get(testRequest, option); - - // 判断响应长度是否为这么多个字,登录跳转响应长度 - // 这种办法虽然在极端情况下可能会出错(而且还挺蠢的),但是是最快的办法中比较准确的了 - return testResponse.getBody().length != COOKIES_ERROR_RESPONSE_LENGTH; - } - -} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/LibraryLogin.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/LibraryLogin.java index 1ae65f1..e4e06d6 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/LibraryLogin.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/LibraryLogin.java @@ -1,9 +1,8 @@ package cn.linghang.mywust.core.service.auth; -import cn.linghang.mywust.core.api.Library; -import cn.linghang.mywust.core.api.UnionAuth; +import cn.linghang.mywust.core.api.LibraryUrls; +import cn.linghang.mywust.core.api.UnionAuthUrls; import cn.linghang.mywust.core.exception.ApiException; -import cn.linghang.mywust.core.exception.BasicException; import cn.linghang.mywust.core.request.library.LibraryRequestFactory; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; @@ -22,9 +21,9 @@ public class LibraryLogin { this.unionLogin = new UnionLogin(requester); } - public String getLibraryLoginCookie(String username, String password, RequestClientOption requestOption) throws ApiException, IOException { + public String getLoginCookie(String username, String password, RequestClientOption requestOption) throws ApiException, IOException { // 获取service ticket以进行进一步的登录 - String serviceTicket = unionLogin.getServiceTicket(username, password, UnionAuth.Service.LIBRARY_SSO_SERVICE, requestOption); + String serviceTicket = unionLogin.getServiceTicket(username, password, UnionAuthUrls.Service.LIBRARY_SSO_SERVICE, requestOption); // 获取登录cookie(session) HttpRequest sessionRequest = LibraryRequestFactory.sessionCookieRequest(serviceTicket); @@ -41,7 +40,7 @@ public class LibraryLogin { public boolean checkCookie(String cookies) throws IOException { RequestClientOption option = RequestClientOption.DEFAULT_OPTION; - HttpRequest testRequest = LibraryRequestFactory.makeHttpRequest(Library.LIBRARY_COOKIE_TEST_URL, null, cookies); + HttpRequest testRequest = LibraryRequestFactory.makeHttpRequest(LibraryUrls.LIBRARY_COOKIE_TEST_URL, null, cookies); HttpResponse testResponse = requester.get(testRequest, option); // 响应居然是JSON,好评! diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/UndergraduateLogin.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/UndergraduateLogin.java new file mode 100644 index 0000000..65f4eaf --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/UndergraduateLogin.java @@ -0,0 +1,110 @@ +package cn.linghang.mywust.core.service.auth; + +import cn.linghang.mywust.core.api.UndergradUrls; +import cn.linghang.mywust.core.api.UnionAuthUrls; +import cn.linghang.mywust.core.exception.ApiException; +import cn.linghang.mywust.core.request.undergrade.BkjxRequestFactory; +import cn.linghang.mywust.network.RequestClientOption; +import cn.linghang.mywust.network.Requester; +import cn.linghang.mywust.network.entitys.HttpRequest; +import cn.linghang.mywust.network.entitys.HttpResponse; +import cn.linghang.mywust.util.PasswordEncoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +public class UndergraduateLogin { + private static final Logger log = LoggerFactory.getLogger(UndergraduateLogin.class); + + private final Requester requester; + + private final UnionLogin unionLogin; + + public UndergraduateLogin(Requester requester) { + this.requester = requester; + this.unionLogin = new UnionLogin(requester); + } + + public String getLoginCookie(String username, String password, RequestClientOption requestOption) throws IOException, ApiException { + // 获取service ticket以进行进一步的登录 + String serviceTicket = unionLogin.getServiceTicket(username, password, UnionAuthUrls.Service.BKJX_SSO_SERVICE, requestOption); + + // 获取登录cookie(session) + HttpRequest sessionRequest = BkjxRequestFactory.sessionCookieRequest(serviceTicket); + HttpResponse sessionResponse = requester.get(sessionRequest, requestOption); + + String cookies = sessionResponse.getCookies(); + if (checkCookies(cookies, requestOption)) { + log.warn("[mywust]: Cookie检查不通过:{}", cookies); + throw new ApiException(ApiException.Code.UNKNOWN_EXCEPTION, "登录获取的Cookie无效"); + } + + return cookies; + } + + /** + *

旧版的登录方式,既相当于直接登录bkjx系统,不建议使用

+ *

注意,这种登录方式的密码和新版可能是不一样的

+ *

不过不论使用哪种登录方式获取到的cookie都是可用的

+ * + * @return 获取到的Cookies + */ + @Deprecated + public String getLoginCookieLegacy(String username, String password, RequestClientOption requestOption) throws IOException, ApiException { + // 获取某段神秘的dataStr(反正官网代码是这么叫的) + HttpRequest dataStringRequest = BkjxRequestFactory.Legacy.dataStringRequest(); + HttpResponse dataStringResponse = requester.post(dataStringRequest, requestOption); + if (dataStringResponse.getBody() == null) { + log.warn("[mywust]: 本科教学系统旧版登录方式:获取dataStr时发生错误"); + throw new ApiException(ApiException.Code.UNKNOWN_EXCEPTION); + } + + String dataString = new String(dataStringResponse.getBody()); + + // 获取登录ticket + String encoded = PasswordEncoder.legacyPassword(username, password, dataString); + HttpRequest ticketRequest = BkjxRequestFactory.Legacy.ticketRedirectRequest(encoded); + ticketRequest.setCookies(dataStringResponse.getCookies()); + + HttpResponse ticketResponse = requester.post(ticketRequest, requestOption); + if (ticketResponse.getBody() == null) { + log.warn("[mywust]: 本科教学系统旧版登录方式:获取登录ticket时发生错误"); + throw new ApiException(ApiException.Code.UNKNOWN_EXCEPTION); + } + + // 使用跳转得到的链接获取cookies + String sessionRedirect = ticketResponse.getHeaders().get("Location"); + if (sessionRedirect == null) { + throw new ApiException(ApiException.Code.BKJX_LEGACY_LOGIN_PASSWORD_WRONG); + } + + HttpRequest sessionRequest = BkjxRequestFactory.makeHttpRequest(sessionRedirect); + HttpResponse sessionResponse = requester.get(sessionRequest, requestOption); + + String cookies = sessionResponse.getCookies(); + if (checkCookies(cookies, requestOption)) { + log.warn("[mywust]: Cookie检查不通过:{}", cookies); + throw new ApiException(ApiException.Code.UNKNOWN_EXCEPTION, "登录获取的Cookie无效"); + } + + return cookies; + } + + private boolean roughCheckCookie(String cookies) { + return cookies == null || !cookies.contains("JSESSIONID") || !cookies.contains("SERVERID"); + } + + private static final int COOKIES_ERROR_RESPONSE_LENGTH = + ("") + .length(); + + public boolean checkCookies(String cookies, RequestClientOption option) throws IOException { + HttpRequest testRequest = BkjxRequestFactory.makeHttpRequest(UndergradUrls.BKJX_TEST_API, null, cookies); + HttpResponse testResponse = requester.get(testRequest, option); + + // 判断响应长度是否为这么多个字,登录跳转响应长度 + // 这种办法虽然在极端情况下可能会出错(而且还挺蠢的),但是是最快的办法中比较准确的了 + return Math.abs(COOKIES_ERROR_RESPONSE_LENGTH - testResponse.getBody().length) > 8; + } +} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/UnionLogin.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/UnionLogin.java index 82b0197..4a8ec0e 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/UnionLogin.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/UnionLogin.java @@ -1,14 +1,12 @@ package cn.linghang.mywust.core.service.auth; import cn.linghang.mywust.core.exception.ApiException; -import cn.linghang.mywust.core.exception.BasicException; import cn.linghang.mywust.core.request.auth.UnionAuthRequestFactory; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.network.entitys.HttpResponse; import cn.linghang.mywust.util.PasswordEncoder; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +34,7 @@ public class UnionLogin { String redirectAddress = unionAuthResponse.getHeaders().get("Location"); if (redirectAddress == null) { - throw new ApiException(this.analyzeFailReason(unionAuthResponse.getBody())); + throw analyzeFailReason(unionAuthResponse.getBody()); } // 获取服务ticket(service ticket,ST) @@ -53,21 +51,34 @@ public class UnionLogin { return new String(serviceTicketResponseData); } - private ApiException.Code analyzeFailReason(byte[] response) { + private ApiException analyzeFailReason(byte[] response) { try { - JsonNode dataNode = new ObjectMapper().readTree(response).get("data"); - switch (dataNode.get("code").asText()) { + String code = new ObjectMapper().readTree(response).get("data").get("code").asText(); + switch (code) { case "PASSERROR": - return ApiException.Code.UNI_LOGIN_PASSWORD_WRONG; + case "FALSE": + return new ApiException(ApiException.Code.UNI_LOGIN_PASSWORD_WRONG); case "NOUSER": - return ApiException.Code.UNI_LOGIN_USER_NOT_EXISTS; + return new ApiException(ApiException.Code.UNI_LOGIN_USER_NOT_EXISTS); case "USERLOCK": - return ApiException.Code.UNI_LOGIN_USER_BANNED; + return new ApiException(ApiException.Code.UNI_LOGIN_USER_BANNED); + case "USERDISABLED": + return new ApiException(ApiException.Code.UNI_LOGIN_USER_DISABLED); + case "ISMODIFYPASS": + return new ApiException(ApiException.Code.UNI_LOGIN_NEED_CHANGE_PASSWORD); + case "USERNOTONLY": + return new ApiException(ApiException.Code.UNI_LOGIN_USER_NOT_ONLY); + case "NOREGISTER": + return new ApiException(ApiException.Code.UNI_LOGIN_NO_REGISTER); + case "TWOVERIFY": + return new ApiException(ApiException.Code.UNI_LOGIN_NEED_TFA); default: - return ApiException.Code.UNKNOWN_EXCEPTION; + log.warn("未知的原因:{}", code); + return new ApiException(ApiException.Code.UNKNOWN_EXCEPTION, "未知的错误原因:" + code); } } catch (Exception e) { - return ApiException.Code.UNKNOWN_EXCEPTION; + log.warn("分析失败原因出错:{}, 响应:{}", e, new String(response)); + return new ApiException(ApiException.Code.UNKNOWN_EXCEPTION, e.toString()); } } } diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/captcha/solver/DdddOcrCaptchaSolver.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/captcha/solver/DdddOcrCaptchaSolver.java new file mode 100644 index 0000000..be91034 --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/captcha/solver/DdddOcrCaptchaSolver.java @@ -0,0 +1,43 @@ +package cn.linghang.mywust.core.service.captcha.solver; + +import cn.linghang.mywust.captcha.SolvedImageCaptcha; +import cn.linghang.mywust.captcha.UnsolvedImageCaptcha; +import cn.linghang.mywust.core.exception.ApiException; +import cn.linghang.mywust.core.request.RequestFactory; +import cn.linghang.mywust.network.Requester; +import cn.linghang.mywust.network.entitys.HttpRequest; +import cn.linghang.mywust.network.entitys.HttpResponse; + +import java.io.IOException; +import java.util.Base64; + +public class DdddOcrCaptchaSolver implements CaptchaSolver { + private final String baseUrl; + + private final Requester requester; + + public DdddOcrCaptchaSolver(String baseUrl, Requester requester) { + this.baseUrl = baseUrl; + this.requester = requester; + } + + @Override + public SolvedImageCaptcha solve(UnsolvedImageCaptcha unsolvedImageCaptcha) throws ApiException { + try { + SolvedImageCaptcha solvedImageCaptcha = new SolvedImageCaptcha(unsolvedImageCaptcha); + + String result = this.ocr(unsolvedImageCaptcha.getImage()); + solvedImageCaptcha.setResult(result); + return solvedImageCaptcha; + } catch (IOException e) { + throw new ApiException(ApiException.Code.NETWORK_EXCEPTION); + } + } + + private String ocr(byte[] data) throws IOException { + HttpRequest request = RequestFactory.makeHttpRequest(baseUrl + "/ocr/b64/text", Base64.getEncoder().encode(data)); + HttpResponse response = requester.post(request); + + return response.getStringBody(); + } +} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/captcha/solver/LocalPaddleOcrCaptchaSolver.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/captcha/solver/LocalPaddleOcrCaptchaSolver.java deleted file mode 100644 index 30ffe14..0000000 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/captcha/solver/LocalPaddleOcrCaptchaSolver.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.linghang.mywust.core.service.captcha.solver; - -import cn.linghang.mywust.captcha.SolvedImageCaptcha; -import cn.linghang.mywust.captcha.UnsolvedImageCaptcha; - -public class LocalPaddleOcrCaptchaSolver implements CaptchaSolver { - @Override - public SolvedImageCaptcha solve(UnsolvedImageCaptcha unsolvedImageCaptcha) { - return null; - } -} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateApiServiceBase.java similarity index 85% rename from mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateApiService.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateApiServiceBase.java index 76ee083..6c7bf29 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateApiServiceBase.java @@ -1,6 +1,6 @@ package cn.linghang.mywust.core.service.graduate; -import cn.linghang.mywust.core.api.Graduate; +import cn.linghang.mywust.core.api.GraduateUrls; import cn.linghang.mywust.core.exception.ApiException; import cn.linghang.mywust.core.request.RequestFactory; import cn.linghang.mywust.network.RequestClientOption; @@ -10,10 +10,10 @@ import cn.linghang.mywust.network.entitys.HttpResponse; import java.io.IOException; -public class GraduateApiService { +public class GraduateApiServiceBase { protected final Requester requester; - public GraduateApiService(Requester requester) { + public GraduateApiServiceBase(Requester requester) { this.requester = requester; } @@ -28,7 +28,7 @@ public class GraduateApiService { } public void checkCookies(String cookie, RequestClientOption option) throws ApiException, IOException { - HttpRequest request = RequestFactory.makeHttpRequest(Graduate.GRADUATE_INDEX_TEST_API, null, cookie); + HttpRequest request = RequestFactory.makeHttpRequest(GraduateUrls.GRADUATE_INDEX_TEST_API, null, cookie); HttpResponse response = requester.get(request, option); this.checkResponse(response); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateCourseTableApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateCourseTableApiService.java index fdb9f7c..1fc3e67 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateCourseTableApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateCourseTableApiService.java @@ -9,13 +9,13 @@ import cn.linghang.mywust.network.entitys.HttpResponse; import java.io.IOException; -public class GraduateCourseTableApiService extends GraduateApiService{ +public class GraduateCourseTableApiService extends GraduateApiServiceBase { public GraduateCourseTableApiService(Requester requester) { super(requester); } - public String getCourseTablePage(String cookie, RequestClientOption option) throws IOException, ApiException { + public String getPage(String cookie, RequestClientOption option) throws IOException, ApiException { HttpRequest request = GraduateRequestFactory.courseTableRequest(cookie); request.addHeaders("Referer", "http://59.68.177.189/pyxx/pygl/kbcx_xs.aspx"); request.addHeaders("Origin", "http://59.68.177.189"); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateScoreApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateScoreApiService.java index 5976674..911f724 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateScoreApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateScoreApiService.java @@ -9,13 +9,13 @@ import cn.linghang.mywust.network.entitys.HttpResponse; import java.io.IOException; -public class GraduateScoreApiService extends GraduateApiService{ +public class GraduateScoreApiService extends GraduateApiServiceBase { public GraduateScoreApiService(Requester requester) { super(requester); } - public String getScorePage(String cookie, RequestClientOption option) throws IOException, ApiException { + public String getPage(String cookie, RequestClientOption option) throws IOException, ApiException { HttpRequest request = GraduateRequestFactory.examScoreInfoRequest(cookie); request.addHeaders("Referer", "http://59.68.177.189/pyxx/leftmenu.aspx"); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateStudentInfoApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateStudentInfoApiService.java index 676347e..df0db45 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateStudentInfoApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateStudentInfoApiService.java @@ -9,13 +9,13 @@ import cn.linghang.mywust.network.entitys.HttpResponse; import java.io.IOException; -public class GraduateStudentInfoApiService extends GraduateApiService { +public class GraduateStudentInfoApiService extends GraduateApiServiceBase { public GraduateStudentInfoApiService(Requester requester) { super(requester); } - public String getStudentInfoPage(String cookie, RequestClientOption option) throws ApiException, IOException { + public String getPage(String cookie, RequestClientOption option) throws ApiException, IOException { HttpRequest request = GraduateRequestFactory.studentInfoRequest(cookie); HttpResponse response = requester.get(request, option); super.checkResponse(response); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateTrainingPlanApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateTrainingPlanApiService.java index 6fe3b89..f23fbc7 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateTrainingPlanApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/graduate/GraduateTrainingPlanApiService.java @@ -9,13 +9,13 @@ import cn.linghang.mywust.network.entitys.HttpResponse; import java.io.IOException; -public class GraduateTrainingPlanApiService extends GraduateApiService{ +public class GraduateTrainingPlanApiService extends GraduateApiServiceBase { public GraduateTrainingPlanApiService(Requester requester) { super(requester); } - public String getCourseTablePage(String cookie, RequestClientOption option) throws IOException, ApiException { + public String getPage(String cookie, RequestClientOption option) throws IOException, ApiException { HttpRequest request = GraduateRequestFactory.trainingPlanPageRequest(cookie); HttpResponse response = requester.get(request, option); super.checkResponse(response); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/CourseTableApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/CourseTableApiService.java deleted file mode 100644 index 5111069..0000000 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/CourseTableApiService.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.linghang.mywust.core.service.undergraduate; - -import cn.linghang.mywust.core.exception.ApiException; -import cn.linghang.mywust.core.exception.ParseException; -import cn.linghang.mywust.core.parser.undergraduate.CourseTableParser; -import cn.linghang.mywust.core.request.undergrade.BkjxRequestFactory; -import cn.linghang.mywust.model.global.Course; -import cn.linghang.mywust.network.RequestClientOption; -import cn.linghang.mywust.network.Requester; -import cn.linghang.mywust.network.entitys.HttpRequest; -import cn.linghang.mywust.network.entitys.HttpResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.List; - -public class CourseTableApiService extends UndergraduateApiService { - - public CourseTableApiService(Requester requester) { - super(requester); - } - - public String getCourseTablePage(String term, String cookies, RequestClientOption requestClientOption) throws IOException, ApiException { - HttpRequest request = BkjxRequestFactory.courseTablePageRequest(term, cookies); - HttpResponse response = requester.post(request, requestClientOption); - - super.checkResponse(response); - - return new String(response.getBody()); - } - -} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergraduateApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradApiServiceBase.java similarity index 67% rename from mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergraduateApiService.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradApiServiceBase.java index 7c2546a..36e171c 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergraduateApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradApiServiceBase.java @@ -1,9 +1,8 @@ package cn.linghang.mywust.core.service.undergraduate; -import cn.linghang.mywust.core.api.Bkjx; +import cn.linghang.mywust.core.api.UndergradUrls; import cn.linghang.mywust.core.exception.ApiException; import cn.linghang.mywust.core.request.RequestFactory; -import cn.linghang.mywust.core.request.undergrade.BkjxRequestFactory; import cn.linghang.mywust.core.util.BkjxUtil; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; @@ -11,11 +10,12 @@ import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.network.entitys.HttpResponse; import java.io.IOException; +import java.util.Map; -public class UndergraduateApiService { +public abstract class UndergradApiServiceBase { protected final Requester requester; - public UndergraduateApiService(Requester requester) { + public UndergradApiServiceBase(Requester requester) { this.requester = requester; } @@ -30,9 +30,12 @@ public class UndergraduateApiService { } public void checkCookies(String cookie, RequestClientOption option) throws ApiException, IOException { - HttpRequest request = RequestFactory.makeHttpRequest(Bkjx.BKJX_TEST_API, null, cookie); + HttpRequest request = RequestFactory.makeHttpRequest(UndergradUrls.BKJX_TEST_API, null, cookie); HttpResponse response = requester.get(request, option); this.checkResponse(response); } + + public abstract String getPage(String cookie, Map params, RequestClientOption option) throws ApiException, IOException; + public abstract String getPage(String cookie, Map params) throws ApiException, IOException; } diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradCourseTableApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradCourseTableApiService.java new file mode 100644 index 0000000..3c4a28b --- /dev/null +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradCourseTableApiService.java @@ -0,0 +1,49 @@ +package cn.linghang.mywust.core.service.undergraduate; + +import cn.linghang.mywust.core.exception.ApiException; +import cn.linghang.mywust.core.request.undergrade.BkjxRequestFactory; +import cn.linghang.mywust.network.RequestClientOption; +import cn.linghang.mywust.network.Requester; +import cn.linghang.mywust.network.entitys.HttpRequest; +import cn.linghang.mywust.network.entitys.HttpResponse; + +import java.io.IOException; +import java.util.Map; + +public class UndergradCourseTableApiService extends UndergradApiServiceBase { + + private static final String[] NECESSARY_PARAMS = {"term"}; + + public UndergradCourseTableApiService(Requester requester) { + super(requester); + } + + @Override + public String getPage(String cookie, Map params, RequestClientOption option) throws ApiException, IOException { + for (String key : NECESSARY_PARAMS) { + if (params.get(key) == null) { + throw new ApiException(ApiException.Code.PARAM_WRONG_EXCEPTION); + } + } + + return this.getPage(params.get(NECESSARY_PARAMS[0]), cookie, option); + } + + @Override + public String getPage(String cookie, Map params) throws ApiException, IOException { + return this.getPage(cookie, params, null); + } + + public String getPage(String term, String cookies, RequestClientOption requestClientOption) throws IOException, ApiException { + HttpRequest request = BkjxRequestFactory.courseTablePageRequest(term, cookies); + HttpResponse response = requester.post(request, requestClientOption); + + super.checkResponse(response); + + return new String(response.getBody()); + } + + public String getPage(String term, String cookies) throws IOException, ApiException { + return getPage(term, cookies, null); + } +} diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/ExamInfoApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradScoreApiService.java similarity index 52% rename from mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/ExamInfoApiService.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradScoreApiService.java index 889eccd..3ba22ee 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/ExamInfoApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradScoreApiService.java @@ -1,27 +1,32 @@ package cn.linghang.mywust.core.service.undergraduate; import cn.linghang.mywust.core.exception.ApiException; -import cn.linghang.mywust.core.exception.ParseException; -import cn.linghang.mywust.core.parser.undergraduate.ExamInfoParser; import cn.linghang.mywust.core.request.undergrade.BkjxRequestFactory; -import cn.linghang.mywust.model.global.ExamInfo; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.network.entitys.HttpResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; -import java.util.List; +import java.util.Map; -public class ExamInfoApiService extends UndergraduateApiService { +public class UndergradScoreApiService extends UndergradApiServiceBase { - public ExamInfoApiService(Requester requester) { + public UndergradScoreApiService(Requester requester) { super(requester); } - public String getExamInfoPage(String cookies, RequestClientOption requestClientOption) throws IOException, ApiException { + @Override + public String getPage(String cookie, Map params, RequestClientOption option) throws ApiException, IOException { + return this.getPage(cookie, option); + } + + @Override + public String getPage(String cookie, Map params) throws ApiException, IOException { + return this.getPage(cookie, params, null); + } + + public String getPage(String cookies, RequestClientOption requestClientOption) throws IOException, ApiException { HttpRequest request = BkjxRequestFactory.examScoreInfoRequest(cookies, "", "", ""); HttpResponse response = requester.post(request, requestClientOption); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/StudentInfoApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradStudentInfoApiService.java similarity index 51% rename from mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/StudentInfoApiService.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradStudentInfoApiService.java index d5c68ab..82e6624 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/StudentInfoApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradStudentInfoApiService.java @@ -8,14 +8,25 @@ import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.network.entitys.HttpResponse; import java.io.IOException; +import java.util.Map; -public class StudentInfoApiService extends UndergraduateApiService { +public class UndergradStudentInfoApiService extends UndergradApiServiceBase { - public StudentInfoApiService(Requester requester) { + public UndergradStudentInfoApiService(Requester requester) { super(requester); } - public String getStudentInfoPage(String cookies, RequestClientOption requestOption) throws IOException, ApiException { + @Override + public String getPage(String cookie, Map params, RequestClientOption option) throws ApiException, IOException { + return this.getPage(cookie, option); + } + + @Override + public String getPage(String cookie, Map params) throws ApiException, IOException { + return this.getPage(cookie, params, null); + } + + public String getPage(String cookies, RequestClientOption requestOption) throws IOException, ApiException { HttpRequest request = BkjxRequestFactory.studentInfoRequest(cookies); HttpResponse response = requester.get(request, requestOption); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/TrainingPlanApiService.java b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradTrainingPlanApiService.java similarity index 52% rename from mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/TrainingPlanApiService.java rename to mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradTrainingPlanApiService.java index ec30750..7d784fe 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/TrainingPlanApiService.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/UndergradTrainingPlanApiService.java @@ -8,14 +8,25 @@ import cn.linghang.mywust.network.entitys.HttpRequest; import cn.linghang.mywust.network.entitys.HttpResponse; import java.io.IOException; +import java.util.Map; -public class TrainingPlanApiService extends UndergraduateApiService { +public class UndergradTrainingPlanApiService extends UndergradApiServiceBase { - public TrainingPlanApiService(Requester requester) { + public UndergradTrainingPlanApiService(Requester requester) { super(requester); } - public String getTrainingPlanPage(String cookies, RequestClientOption requestClientOption) throws IOException, ApiException { + @Override + public String getPage(String cookie, Map params, RequestClientOption option) throws ApiException, IOException { + return this.getPage(cookie, option); + } + + @Override + public String getPage(String cookie, Map params) throws ApiException, IOException { + return this.getPage(cookie, params, null); + } + + public String getPage(String cookies, RequestClientOption requestClientOption) throws IOException, ApiException { HttpRequest request = BkjxRequestFactory.trainingPlanPageRequest(cookies); HttpResponse response = requester.get(request, requestClientOption); diff --git a/mywust-core/src/main/java/cn/linghang/mywust/core/util/BkjxUtil.java b/mywust-core/src/main/java/cn/linghang/mywust/core/util/BkjxUtil.java index 274e338..4bc13ac 100644 --- a/mywust-core/src/main/java/cn/linghang/mywust/core/util/BkjxUtil.java +++ b/mywust-core/src/main/java/cn/linghang/mywust/core/util/BkjxUtil.java @@ -1,7 +1,5 @@ package cn.linghang.mywust.core.util; -import cn.linghang.mywust.core.api.Bkjx; - import java.nio.charset.StandardCharsets; /** diff --git a/mywust-model/src/main/java/cn/linghang/mywust/model/global/ExamInfo.java b/mywust-model/src/main/java/cn/linghang/mywust/model/global/Score.java similarity index 98% rename from mywust-model/src/main/java/cn/linghang/mywust/model/global/ExamInfo.java rename to mywust-model/src/main/java/cn/linghang/mywust/model/global/Score.java index 771d189..03a93a0 100644 --- a/mywust-model/src/main/java/cn/linghang/mywust/model/global/ExamInfo.java +++ b/mywust-model/src/main/java/cn/linghang/mywust/model/global/Score.java @@ -20,7 +20,7 @@ import lombok.NoArgsConstructor; @Builder @NoArgsConstructor @AllArgsConstructor -public class ExamInfo { +public class Score { /** * 序号id,在某些场景下可能会有用 */ diff --git a/mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/RedirectInterceptor.java b/mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/RedirectInterceptor.java index 495b7c7..74c6a83 100644 --- a/mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/RedirectInterceptor.java +++ b/mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/RedirectInterceptor.java @@ -13,9 +13,9 @@ public class RedirectInterceptor implements Interceptor { Response response = chain.proceed(request); String location = response.headers().get("Location"); - if (location != null) { - System.out.println(("Request redirected to:" + location)); - } +// if (location != null) { +// System.out.println(("Request redirected to:" + location)); +// } return response; } diff --git a/mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/SimpleOkhttpRequester.java b/mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/SimpleOkhttpRequester.java index 75940aa..d7e9b12 100644 --- a/mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/SimpleOkhttpRequester.java +++ b/mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/SimpleOkhttpRequester.java @@ -1,11 +1,10 @@ package cn.linghang.mywust.network.okhttp; -import cn.linghang.mywust.network.entitys.HttpRequest; -import cn.linghang.mywust.network.entitys.HttpResponse; import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.Requester; +import cn.linghang.mywust.network.entitys.HttpRequest; +import cn.linghang.mywust.network.entitys.HttpResponse; import cn.linghang.mywust.util.StringUtil; -import com.fasterxml.jackson.databind.ObjectMapper; import okhttp3.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,7 +12,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Proxy; -import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -33,7 +31,7 @@ import java.util.concurrent.TimeUnit; * * @author lensfrex * @create 2022-10-15 09:49 - * @edit 2022-10-19 21:30 + * @edit 2023-01-21 15:35 */ public class SimpleOkhttpRequester implements Requester { private static final Logger log = LoggerFactory.getLogger(SimpleOkhttpRequester.class); @@ -46,7 +44,7 @@ public class SimpleOkhttpRequester implements Requester { * 默认的,多例模式的SimpleOkhttpRequester构造方法 */ public SimpleOkhttpRequester() { - this(new OkHttpClient(), false); + this(false); } /** @@ -55,11 +53,12 @@ public class SimpleOkhttpRequester implements Requester { * @param useSingletonClient 是否使用单例模式 */ public SimpleOkhttpRequester(boolean useSingletonClient) { - this(new OkHttpClient(), useSingletonClient); + this.useSingletonClient = useSingletonClient; + this.setRootClient(); } /** - * 使用特定okhttpClient对象并且指定是否使用单例模式的SimpleOkhttpRequester私有构造方法 + * 使用特定okhttpClient对象作为rootClient,仅在rootClient为null时起作用,并指定是否使用单例模式的SimpleOkhttpRequester私有构造方法 * * @param okHttpClient okhttpClient对象 * @param useSingletonClient 是否使用单例模式 @@ -70,50 +69,94 @@ public class SimpleOkhttpRequester implements Requester { } /** - * 指定client参数选项的SimpleOkhttpRequester构造方法,默认不使用单例模式 + * 指定client参数选项的SimpleOkhttpRequester构造方法,仅在rootClient为null时起作用,默认不使用单例模式 * - * @param requestClientOption client参数选项 + * @param requestClientOption client参数选项,为null时使用默认选项 */ public SimpleOkhttpRequester(RequestClientOption requestClientOption) { this(requestClientOption, false); } /** - * 指定client参数选项的SimpleOkhttpRequester构造方法,并且指定是否使用单例模式 + * 指定client参数选项的SimpleOkhttpRequester构造方法,仅在rootClient为null时起作用,并且指定是否使用单例模式 * - * @param requestClientOption client参数选项 + * @param requestClientOption client参数选项,为null时使用默认选项 * @param useSingletonClient 是否使用单例模式 */ public SimpleOkhttpRequester(RequestClientOption requestClientOption, boolean useSingletonClient) { + this(requestClientOption, useSingletonClient, null); + } + + /** + * 指定client参数选项的SimpleOkhttpRequester构造方法,仅在rootClient为null时起作用,并且指定是否使用单例模式以及CookieJar + * + * @param requestClientOption client参数选项,为null时使用默认选项 + * @param useSingletonClient 是否使用单例模式 + * @param cookieJar 指定的cookieJar + */ + public SimpleOkhttpRequester(RequestClientOption requestClientOption, boolean useSingletonClient, CookieJar cookieJar) { this.useSingletonClient = useSingletonClient; - this.setRootClient(buildClient(new OkHttpClient.Builder(), requestClientOption)); + if (rootClient == null) { + synchronized (SimpleOkhttpRequester.class) { + if (rootClient == null ) { + rootClient = this.buildClient(new OkHttpClient.Builder(), requestClientOption, cookieJar); + } + } + } } + /** + * 设置指定的client为根client,仅在rootClient为null时设置 + * + * @param okHttpClient 传入的client + */ private void setRootClient(OkHttpClient okHttpClient) { if (rootClient == null) { synchronized (SimpleOkhttpRequester.class) { - if (rootClient == null) { + if (rootClient == null ) { rootClient = okHttpClient; } } } } + /** + * 设置一个新的根client,只在rootClient为null时设置,保证根client只有一个 + */ + private void setRootClient() { + if (rootClient == null) { + synchronized (SimpleOkhttpRequester.class) { + if (rootClient == null) { + rootClient = new OkHttpClient(); + } + } + } + } + /** * 构建一个okhttpClient * * @param builder okhttpClient.Builder - * @param requestClientOption client参数选项 + * @param requestClientOption client参数选项,当null时为默认的option + * @param cookieJar 提供的CookieJar,当为null时不设置 * @return 构建好的client */ - private OkHttpClient buildClient(OkHttpClient.Builder builder, RequestClientOption requestClientOption) { + private OkHttpClient buildClient(OkHttpClient.Builder builder, RequestClientOption requestClientOption, CookieJar cookieJar) { + if (requestClientOption == null) { + requestClientOption = new RequestClientOption(); + } + builder.callTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS) .readTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS) .connectTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS) .followRedirects(requestClientOption.isFallowUrlRedirect()) - .addInterceptor(new RedirectInterceptor()) - .sslSocketFactory(TrustAllCert.getSSLSocketFactory(), TrustAllCert.getX509TrustManager()) - .hostnameVerifier(TrustAllCert.getHostnameVerifier()); + .addInterceptor(new RedirectInterceptor()); + + // 是否忽略SSL错误 + if (requestClientOption.isIgnoreSSLError()) { + builder.sslSocketFactory(TrustAllCert.getSSLSocketFactory(), TrustAllCert.getX509TrustManager()) + .hostnameVerifier(TrustAllCert.getHostnameVerifier()); + } // 设置代理 RequestClientOption.Proxy proxyOption = requestClientOption.getProxy(); @@ -124,6 +167,11 @@ public class SimpleOkhttpRequester implements Requester { builder.proxy(proxy); } + // 设置CookieJar + if (cookieJar != null) { + builder.cookieJar(cookieJar); + } + return builder.build(); } @@ -139,14 +187,9 @@ public class SimpleOkhttpRequester implements Requester { return rootClient; } - return buildClient(rootClient.newBuilder(), requestClientOption); + return buildClient(rootClient.newBuilder(), requestClientOption, null); } - /** - * json的content-type - */ - private static final String JSON_CONTENT_TYPE = "application/json; charset=utf-8"; - /** * 默认的content-type(form) */ @@ -273,11 +316,15 @@ public class SimpleOkhttpRequester implements Requester { * @throws IOException 如果网络请求有异常 */ private HttpResponse doRequest(RequestMethod requestMethod, HttpRequest httpRequest, RequestClientOption requestClientOption) throws IOException { + if (requestClientOption == null) { + requestClientOption = RequestClientOption.DEFAULT_OPTION; + } + OkHttpClient client = getOkhttpClient(requestClientOption); Request request = this.buildRequest(requestMethod, httpRequest); log.debug("------------Do Request------------"); - log.debug("Request Options: {}" ,requestClientOption); + log.debug("Request Options: {}", requestClientOption); log.debug("Request: {}", request); log.debug("Headers: {}", request.headers()); @@ -289,18 +336,19 @@ public class SimpleOkhttpRequester implements Requester { return this.doRequest(RequestMethod.GET, httpRequest, requestClientOption); } + @Override + public HttpResponse get(HttpRequest httpRequest) throws IOException { + return this.doRequest(RequestMethod.GET, httpRequest, null); + } + @Override public HttpResponse post(HttpRequest request, RequestClientOption requestClientOption) throws IOException { return this.doRequest(RequestMethod.POST, request, requestClientOption); } @Override - public HttpResponse postJson(HttpRequest request, Object requestBody, RequestClientOption requestClientOption) throws IOException { - String json = new ObjectMapper().writeValueAsString(requestBody); - request.setData(json.getBytes(StandardCharsets.UTF_8)); - request.getHeaders().put("Content-Type", JSON_CONTENT_TYPE); - - return this.doRequest(RequestMethod.POST, request, requestClientOption); + public HttpResponse post(HttpRequest request) throws IOException { + return this.doRequest(RequestMethod.POST, request, null); } @Override @@ -308,8 +356,19 @@ public class SimpleOkhttpRequester implements Requester { return this.doRequest(RequestMethod.PUT, request, requestClientOption); } + @Override + public HttpResponse put(HttpRequest request) throws IOException { + return this.doRequest(RequestMethod.PUT, request, null); + } + @Override public HttpResponse delete(HttpRequest request, RequestClientOption requestClientOption) throws IOException { return this.doRequest(RequestMethod.DELETE, request, requestClientOption); } + + @Override + public HttpResponse delete(HttpRequest request) throws IOException { + return this.doRequest(RequestMethod.DELETE, request, null); + } + } diff --git a/mywust-network/src/main/java/cn/linghang/mywust/network/RequestClientOption.java b/mywust-network/src/main/java/cn/linghang/mywust/network/RequestClientOption.java index de480bf..7affa4c 100644 --- a/mywust-network/src/main/java/cn/linghang/mywust/network/RequestClientOption.java +++ b/mywust-network/src/main/java/cn/linghang/mywust/network/RequestClientOption.java @@ -1,27 +1,70 @@ package cn.linghang.mywust.network; +import lombok.Builder; import lombok.Data; @Data +@Builder public class RequestClientOption { private Proxy proxy; private long timeout; - private boolean fallowUrlRedirect = false; + private boolean fallowUrlRedirect; + + private boolean ignoreSSLError; @Data + @Builder public static class Proxy { private String address; private int port; } + public RequestClientOption() { + this.proxy = null; + this.timeout = 5; + this.fallowUrlRedirect = false; + this.ignoreSSLError = true; + } + + public RequestClientOption(Proxy proxy, long timeout, boolean fallowUrlRedirect, boolean ignoreSSLError) { + this.proxy = proxy; + this.timeout = timeout; + this.fallowUrlRedirect = fallowUrlRedirect; + this.ignoreSSLError = ignoreSSLError; + } + public static final RequestClientOption DEFAULT_OPTION = newDefaultOption(); private static RequestClientOption newDefaultOption() { - RequestClientOption option = new RequestClientOption(); - option.setTimeout(5); - option.setProxy(null); - option.setFallowUrlRedirect(false); + return new ConstantRequestClientOption(); + } + + /** + * 常量化的RequestClientOption,对其使用setter时不会起任何作用 + */ + public static class ConstantRequestClientOption extends RequestClientOption { + @Override + public Proxy getProxy() { + return super.getProxy(); + } + + @Override + public long getTimeout() { + return super.getTimeout(); + } + + @Override + public boolean isFallowUrlRedirect() { + return super.isFallowUrlRedirect(); + } + + @Override + public void setProxy(Proxy proxy) {} + + @Override + public void setTimeout(long timeout) {} - return option; + @Override + public void setFallowUrlRedirect(boolean fallowUrlRedirect) {} } } diff --git a/mywust-network/src/main/java/cn/linghang/mywust/network/Requester.java b/mywust-network/src/main/java/cn/linghang/mywust/network/Requester.java index 0ec7494..1aed9f5 100644 --- a/mywust-network/src/main/java/cn/linghang/mywust/network/Requester.java +++ b/mywust-network/src/main/java/cn/linghang/mywust/network/Requester.java @@ -21,50 +21,47 @@ public interface Requester { * 发送Get请求 * * @param request 请求体 - * @param requestClientOption 请求选项 + * @param requestClientOption 请求选项,为null时,使用默认的选项 * @return 响应数据 * @throws IOException 如果网络请求有异常 */ HttpResponse get(HttpRequest request, RequestClientOption requestClientOption) throws IOException; + HttpResponse get(HttpRequest request) throws IOException; + /** * 发送Post请求 * * @param request 请求体 - * @param requestClientOption 请求选项 + * @param requestClientOption 请求选项,为null时,使用默认的选项 * @return 响应数据 * @throws IOException 如果网络请求有异常 */ HttpResponse post(HttpRequest request, RequestClientOption requestClientOption) throws IOException; - /** - * 发送Post请求,并将对象自动封装成json - * - * @param request 请求体 - * @param requestClientOption 请求选项 - * @return 响应数据 - * @throws IOException 如果网络请求有异常 - */ - HttpResponse postJson(HttpRequest request, Object requestBody, RequestClientOption requestClientOption) throws IOException; + HttpResponse post(HttpRequest request) throws IOException; /** * 发送Put请求 * * @param request 请求体 - * @param requestClientOption 请求选项 + * @param requestClientOption 请求选项,为null时,使用默认的选项 * @return 响应数据 * @throws IOException 如果网络请求有异常 */ HttpResponse put(HttpRequest request, RequestClientOption requestClientOption) throws IOException; + HttpResponse put(HttpRequest request) throws IOException; + /** * 发送Delete请求 * * @param request 请求体 - * @param requestClientOption 请求选项 + * @param requestClientOption 请求选项,为null时,使用默认的选项 * @return 响应数据 * @throws IOException 如果网络请求有异常 */ HttpResponse delete(HttpRequest request, RequestClientOption requestClientOption) throws IOException; + HttpResponse delete(HttpRequest request) throws IOException; } diff --git a/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/HttpRequest.java b/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/HttpRequest.java index 79ed615..1ff802a 100644 --- a/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/HttpRequest.java +++ b/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/HttpRequest.java @@ -1,12 +1,15 @@ package cn.linghang.mywust.network.entitys; +import lombok.Builder; import lombok.Data; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @Data +@Builder public class HttpRequest { private static final Map DEFAULT_HEADERS = initDefaultHeaders(); @@ -33,6 +36,13 @@ public class HttpRequest { headers = new HashMap<>(DEFAULT_HEADERS); } + public HttpRequest(URL url, Map headers, String cookies, byte[] data) { + this.url = url; + this.headers = headers; + this.cookies = cookies; + this.data = data; + } + public HttpRequest addHeaders(Map headers) { this.headers.putAll(headers); return this; @@ -43,6 +53,18 @@ public class HttpRequest { return this; } + public String getStringData() { + return new String(this.data); + } + + public void setData(byte[] data) { + this.data = data; + } + + public void setData(String stringData) { + this.data = stringData.getBytes(StandardCharsets.UTF_8); + } + @Override public String toString() { final StringBuffer sb = new StringBuffer("HttpRequest{"); @@ -57,44 +79,4 @@ public class HttpRequest { sb.append('}'); return sb.toString(); } - - public static HttpRequestBuilder builder() { - return new HttpRequestBuilder(); - } - - public static class HttpRequestBuilder { - private final HttpRequest httpRequest; - - private HttpRequestBuilder() { - httpRequest = new HttpRequest(); - } - - public static HttpRequestBuilder aHttpRequest() { - return new HttpRequestBuilder(); - } - - public HttpRequestBuilder url(URL url) { - httpRequest.setUrl(url); - return this; - } - - public HttpRequestBuilder headers(Map headers) { - httpRequest.setHeaders(headers); - return this; - } - - public HttpRequestBuilder cookies(String cookies) { - httpRequest.setCookies(cookies); - return this; - } - - public HttpRequestBuilder data(byte[] data) { - httpRequest.setData(data); - return this; - } - - public HttpRequest build() { - return httpRequest; - } - } } diff --git a/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/HttpResponse.java b/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/HttpResponse.java index 8f7e2d8..ef0dec0 100644 --- a/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/HttpResponse.java +++ b/mywust-network/src/main/java/cn/linghang/mywust/network/entitys/HttpResponse.java @@ -1,10 +1,17 @@ package cn.linghang.mywust.network.entitys; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; +import java.nio.charset.StandardCharsets; import java.util.Map; @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class HttpResponse { public static final int HTTP_OK = 200; public static final int HTTP_RESOURCE_CREATED = 201; @@ -26,6 +33,18 @@ public class HttpResponse { private byte[] body; + public String getStringBody() { + return new String(body); + } + + public void setBody(byte[] body) { + this.body = body; + } + + public void setBody(String stringBody) { + this.body = stringBody.getBytes(StandardCharsets.UTF_8); + } + @Override public String toString() { final StringBuffer sb = new StringBuffer("HttpResponse{"); @@ -39,39 +58,4 @@ public class HttpResponse { sb.append('}'); return sb.toString(); } - - public static HttpResponseBuilder builder() { - return new HttpResponseBuilder(); - } - - public static final class HttpResponseBuilder { - private final HttpResponse httpResponse; - - private HttpResponseBuilder() { - httpResponse = new HttpResponse(); - } - - public static HttpResponseBuilder aHttpResponse() { - return new HttpResponseBuilder(); - } - - public HttpResponseBuilder headers(Map headers) { - httpResponse.setHeaders(headers); - return this; - } - - public HttpResponseBuilder cookies(String cookies) { - httpResponse.setCookies(cookies); - return this; - } - - public HttpResponseBuilder body(byte[] body) { - httpResponse.setBody(body); - return this; - } - - public HttpResponse build() { - return httpResponse; - } - } }