Compare commits

...

12 Commits

Author SHA1 Message Date
lensfrex 10fff740cd
feat: 添加maven中央仓库相关设置 1 year ago
lensfrex 5da31b26d1
feat: 本科生:新增登陆时新生信息未录入或毕业生删号错误处理 1 year ago
lensfrex 0ca9d1a48d
ref: 小更README 1 year ago
lensfrex 95a43520ca
[fix] 修复StringUtil: 当前学期字符串生成时,月份不正确导致的春秋期判断错误 1 year ago
lensfrex 736dc78d1b
ref: 移动RequestFactory至network通用包 1 year ago
lensfrex 965562b69e
impl: 图书馆:图书馆全部功能实现(图书详情获取;书籍搜索;馆藏信息查询;当前/历史/即将过期借阅查询;图书封面地址获取) 1 year ago
lensfrex 99e1ea7c8f
fix: 图书馆:修复图书馆登录获取到的cookie不正确的问题 1 year ago
lensfrex c13aa2f56f
feat: 本科生:新增在“专属选课时间段”被“封号”的判断处理 1 year ago
lensfrex 5fd5099181
ref: 图书馆:分散各接口为独立的类,而不是挤在一起 1 year ago
lensfrex e186a0d9f0
feat: 物理实验系统:新增cookie验证 1 year ago
lensfrex b7c61453c5
feat: 研究生:新增验证码错误自动重试; 1 year ago
lensfrex bf828e3418
ref: 重新修改包名以及groupId 1 year ago
  1. 24
      README.md
  2. 41
      mywust-common/pom.xml
  3. 3
      mywust-common/src/main/java/cn/wustlinghang/mywust/captcha/SolvedImageCaptcha.java
  4. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/captcha/UnsolvedImageCaptcha.java
  5. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/global/Building.java
  6. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/global/Campus.java
  7. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/global/Classroom.java
  8. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/global/College.java
  9. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/global/Course.java
  10. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/global/Score.java
  11. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/global/StudentInfo.java
  12. 20
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/PagingResult.java
  13. 61
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/origin/BaseLoanBook.java
  14. 67
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/origin/BookSearchRequest.java
  15. 80
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/origin/BookSearchResult.java
  16. 12
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/origin/CurrentLoanBook.java
  17. 12
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/origin/HistoryLoanBook.java
  18. 51
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/parsed/BookDetail.java
  19. 56
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/parsed/BookHolding.java
  20. 69
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/library/parsed/BookSearchResult.java
  21. 4
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/physics/PhysicsCourse.java
  22. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/data/undergrad/ExamDelayApplication.java
  23. 21
      mywust-common/src/main/java/cn/wustlinghang/mywust/exception/ApiException.java
  24. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/exception/BasicException.java
  25. 2
      mywust-common/src/main/java/cn/wustlinghang/mywust/exception/ParseException.java
  26. 46
      mywust-core/pom.xml
  27. 7
      mywust-core/src/main/java/cn/linghang/mywust/core/parser/Parser.java
  28. 40
      mywust-core/src/main/java/cn/linghang/mywust/core/request/factory/library/request/SearchRequest.java
  29. 9
      mywust-core/src/main/java/cn/linghang/mywust/core/request/service/captcha/solver/CaptchaSolver.java
  30. 66
      mywust-core/src/main/java/cn/linghang/mywust/core/request/service/library/LibraryApiService.java
  31. 20
      mywust-core/src/main/java/cn/linghang/mywust/core/request/service/library/LibraryApiServiceBase.java
  32. 32
      mywust-core/src/main/java/cn/linghang/mywust/core/util/BkjxUtil.java
  33. 2
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/api/ConstantParams.java
  34. 2
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/api/GraduateUrls.java
  35. 14
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/api/LibraryUrls.java
  36. 2
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/api/PhysicsSystemUrls.java
  37. 2
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/api/UndergradUrls.java
  38. 2
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/api/UnionAuthUrls.java
  39. 6
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/HuangjiahuClassroomNameParser.java
  40. 7
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/Parser.java
  41. 10
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/graduate/GraduateCourseTableParser.java
  42. 8
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/graduate/GraduateScoreParser.java
  43. 10
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/graduate/GraduateStudentInfoPageParser.java
  44. 13
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/graduate/GraduateTrainingPlanPageParser.java
  45. 12
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/physics/PhysicsCoursePageParser.java
  46. 6
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/physics/PhysicsIndexPageParser.java
  47. 8
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/physics/PhysicsScoreListPageParser.java
  48. 10
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/physics/PhysicsScorePageParser.java
  49. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/UndergradCourseTableParser.java
  50. 6
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/UndergradCreditStatusIndexParser.java
  51. 6
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/UndergradCreditStatusParser.java
  52. 10
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/UndergradExamDelayParser.java
  53. 10
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/UndergradScoreParser.java
  54. 10
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/UndergradStudentInfoPageParser.java
  55. 6
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/UndergradTrainingPlanPageParser.java
  56. 10
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/global/GlobalCourseTableParser.java
  57. 8
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/global/UndergradAllCourseScheduleParser.java
  58. 8
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/parser/undergraduate/global/UndergradTeacherCourseParser.java
  59. 10
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/factory/auth/UnionAuthRequestFactory.java
  60. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/factory/graduate/GraduateRequestFactory.java
  61. 47
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/factory/library/LibraryRequestFactory.java
  62. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/factory/physics/PhysicsSystemRequestFactory.java
  63. 15
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/factory/undergrade/BkjxRequestFactory.java
  64. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/factory/undergrade/global/BkjxAllCourseRequestFactory.java
  65. 57
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/auth/GraduateLogin.java
  66. 27
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/auth/LibraryLogin.java
  67. 36
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/auth/PhysicsLogin.java
  68. 60
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/auth/UndergraduateLogin.java
  69. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/auth/UnionLogin.java
  70. 9
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/captcha/solver/CaptchaSolver.java
  71. 18
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/captcha/solver/DdddOcrCaptchaSolver.java
  72. 22
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/captcha/solver/LinghangOcrServiceCaptchaSolver.java
  73. 18
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/graduate/GraduateApiServiceBase.java
  74. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/graduate/GraduateCourseTableApiService.java
  75. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/graduate/GraduateScoreApiService.java
  76. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/graduate/GraduateStudentInfoApiService.java
  77. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/graduate/GraduateTrainingPlanApiService.java
  78. 82
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/library/BaseLibraryApiService.java
  79. 59
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/library/BookCoverImageUrlApiService.java
  80. 70
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/library/BookDetailApiService.java
  81. 39
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/library/BookHoldingApiService.java
  82. 52
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/library/CurrentLoanApiService.java
  83. 53
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/library/LoanHistoryApiService.java
  84. 56
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/library/OverdueSoonApiService.java
  85. 68
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/library/SearchApiService.java
  86. 8
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/physics/PhysicsApiServiceBase.java
  87. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/physics/PhysicsCourseApiService.java
  88. 22
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/physics/PhysicsScoreApiService.java
  89. 27
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/UndergradApiServiceBase.java
  90. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/UndergradCourseTableApiService.java
  91. 20
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/UndergradCreditStatusApiService.java
  92. 14
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/UndergradExamDelayApiService.java
  93. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/UndergradScoreApiService.java
  94. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/UndergradStudentInfoApiService.java
  95. 16
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/UndergradTrainingPlanApiService.java
  96. 18
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/global/UndergradAllCourseScheduleApiService.java
  97. 24
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/global/UndergradBuildingIdApiService.java
  98. 18
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/global/UndergradClassroomCourseApiService.java
  99. 18
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/request/service/undergraduate/global/UndergradTeacherCourseApiService.java
  100. 70
      mywust-core/src/main/java/cn/wustlinghang/mywust/core/util/BkjxUtil.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -6,7 +6,7 @@
核心代码来自武科大助手后端爬虫模块,在此基础上进行部分修改以适用于各种平台,因此不会使用重量级的框架,尽量保证仅使用原生java或jvm兼容的语言即可使用,是一个比较~~轻量~~的库
由于处在早期阶段,因此项目结构随时可能发生巨大变化,在正式版出来前请勿重度依赖
由于处在早期阶段,因此项目结构以及外部接口随时可能发生巨大变化,在正式版出来前请勿重度依赖,当前仅作为算法以及处理过程参考使用
后续可能会根据需要新增其他语言的实现以提供给其他语言和平台的使用
@ -35,6 +35,11 @@
- 成绩查询
- 图书馆
- 登录
- 图书详情查询
- 图书封面Url查询
- 图书馆藏信息查询
- 当前借阅、历史借阅、即将逾期借阅信息查询
- 图书搜索
...and more...
</details>
@ -53,23 +58,18 @@ JDK版本:1.8及以上,推荐JDK 11及以上
## 使用说明
### 在项目中引用mywust-core
目前该项目发布在Github Package上,如遇网络问题请自备工具解决
关于如何在自己的项目中引用:
> 文档?什么文档?不知道不知道
> 以后再说
- Maven项目请参阅:[使用 Apache Maven 注册表](https://docs.github.com/zh/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry)
- Gradle项目请参阅:[使用 Gradle 注册表](https://docs.github.com/zh/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry)
### 在项目中引用mywust-core
配置好后,直接在`pom.xml`中引用即可:
在`pom.xml`中引用核心即可:
```xml
<dependency>
<groupId>cn.linghang</groupId>
<groupId>cn.wustlinghang.mywust</groupId>
<artifactId>mywust-core</artifactId>
<version>0.0.1-fixed</version>
<version>0.0.2-beta</version>
</dependency>
```

@ -4,17 +4,56 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mywust</artifactId>
<groupId>cn.linghang</groupId>
<groupId>cn.wustlinghang.mywust</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mywust-common</artifactId>
<name>${project.artifactId}</name>
<description>The API encapsulations of WUST's official web service. Module `${project.artifactId}`</description>
<url>https://github.com/LingHangStudio/mywust</url>
<scm>
<url>https://github.com/LingHangStudio/mywust</url>
<connection>scm:git:https://github.com/LingHangStudio/mywust.git</connection>
<developerConnection>scm:git:https://github.com/LingHangStudio/mywust.git</developerConnection>
<tag>${project.parent.version}</tag>
</scm>
<developers>
<developer>
<id>lensfrex</id>
<name>lensfrex</name>
<email>lensferno@outlook.com</email>
<url>https://github.com/lensferno</url>
<organization>wustlinghang</organization>
<organizationUrl>https://github.com/LingHangStudio</organizationUrl>
<timezone>+8</timezone>
</developer>
</developers>
<licenses>
<license>
<name>MIT License</name>
<url>https://mit-license.org/</url>
</license>
</licenses>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jackson-annotations.version>2.15.2</jackson-annotations.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson-annotations.version}</version>
</dependency>
</dependencies>
</project>

@ -1,6 +1,5 @@
package cn.linghang.mywust.captcha;
package cn.wustlinghang.mywust.captcha;
import lombok.Data;
import lombok.Getter;
/**

@ -1,4 +1,4 @@
package cn.linghang.mywust.captcha;
package cn.wustlinghang.mywust.captcha;
import lombok.AllArgsConstructor;
import lombok.Data;

@ -1,4 +1,4 @@
package cn.linghang.mywust.data.global;
package cn.wustlinghang.mywust.data.global;
import java.util.StringJoiner;

@ -1,4 +1,4 @@
package cn.linghang.mywust.data.global;
package cn.wustlinghang.mywust.data.global;
import java.util.StringJoiner;

@ -1,4 +1,4 @@
package cn.linghang.mywust.data.global;
package cn.wustlinghang.mywust.data.global;
import lombok.AllArgsConstructor;
import lombok.Builder;

@ -1,4 +1,4 @@
package cn.linghang.mywust.data.global;
package cn.wustlinghang.mywust.data.global;
import java.util.StringJoiner;

@ -1,4 +1,4 @@
package cn.linghang.mywust.data.global;
package cn.wustlinghang.mywust.data.global;
import lombok.AllArgsConstructor;
import lombok.Builder;

@ -1,4 +1,4 @@
package cn.linghang.mywust.data.global;
package cn.wustlinghang.mywust.data.global;
import lombok.AllArgsConstructor;
import lombok.Builder;

@ -1,4 +1,4 @@
package cn.linghang.mywust.data.global;
package cn.wustlinghang.mywust.data.global;
import lombok.AllArgsConstructor;
import lombok.Builder;

@ -0,0 +1,20 @@
package cn.wustlinghang.mywust.data.library;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PagingResult<T> {
private int currentPage;
private int pageSize;
private int totalPage;
private int totalResult;
private T data;
}

@ -0,0 +1,61 @@
package cn.wustlinghang.mywust.data.library.origin;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 响应回来的书籍信息借阅历史当前借阅即将逾期等的书目字段
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class BaseLoanBook {
protected String bibId;
protected String title;
protected String author;
/**
* 借书时间
*/
protected String loanDate;
protected String location;
protected String barCode;
/**
* 图书属性信息
*/
@JsonProperty("bibAttrs")
protected BookAttribute bookAttribute;
/**
* 图书属性
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class BookAttribute {
protected String isbn;
protected String publisher;
@JsonProperty("pub_year")
protected String publishYear;
protected String price;
/**
* 索书号
*/
@JsonProperty("callno")
protected String callNumber;
/**
* 书类编号
*/
@JsonProperty("classno")
protected String classNumber;
}
}

@ -0,0 +1,67 @@
package cn.wustlinghang.mywust.data.library.origin;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class BookSearchRequest {
private List<Object> filterFieldList = new ArrayList<>();
private String collapseField = "groupId";
private String sortType = "desc";
private String indexName = "idx.opac";
private String sortField = "relevance";
private List<QueryFieldListItem> queryFieldList = new ArrayList<>(1);
private int pageSize;
private int page;
public BookSearchRequest(String keyWord, int pageSize, int page) {
this.pageSize = pageSize;
this.page = page;
this.queryFieldList.add(new QueryFieldListItem(keyWord));
}
@Data
public static class QueryFieldListItem {
private String field = "all";
private String operator = "*";
private int logic = 0;
private List<String> values = new ArrayList<>(1);
public QueryFieldListItem(String keyWord) {
values.add(keyWord);
}
}
public static class Builder {
private int pageSize;
private int page;
private String keyword;
private Builder() {
}
public Builder pageSize(int pageSize) {
this.pageSize = pageSize;
return this;
}
public Builder page(int page) {
this.page = page;
return this;
}
public Builder keyword(String keyword) {
this.keyword = keyword;
return this;
}
public BookSearchRequest build() {
return new BookSearchRequest(keyword, pageSize, page);
}
}
}

@ -0,0 +1,80 @@
package cn.wustlinghang.mywust.data.library.origin;
import cn.wustlinghang.mywust.data.library.parsed.BookHolding;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class BookSearchResult {
private String bibId;
private String title;
private String author;
@JsonProperty("abstract")
private String summary;
private String publisher;
private List<String> holdingTypes;
@JsonProperty("callno")
private List<String> callNumber;
/**
* 文献类型
*/
private String docType;
private String groupId;
private String isbn;
/**
* 图书馆系统中的图书编号
*/
private String bibNo;
/**
* 图书总数
*/
private int itemCount;
/**
* 在借数量
*/
private int circCount;
@JsonProperty("pub_year")
private String pubYear;
@JsonProperty("classno")
private String classNumber;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private List<BookHolding> holdings;
}
/*
bibId: 图书馆系统中的图书ID用于唯一标识一本图书
holdingTypes: 图书的持有类型此处为print表示该图书以纸质形式持有
author: 作者此处为Walter Savitch著表示该图书的作者是Walter Savitch
callno: 索书号此处为["TP312JA/E26=4/1","TP312JA/E26=4/2"]表示该图书的索书号是TP312JA/E26=4/1和TP312JA/E26=4/2
docType: 文献类型此处为doc.02表示该图书的文献类型为doc.02
groupId: 分组ID此处为1e24652f1d98f0586dc6468136f8eba6可能是用于图书分类的一个标识
isbn: ISBN号此处为7115152888 (v. 1)表示该图书的ISBN号是7115152888其中(v. 1)可能表示版本号
bibNo: 图书馆系统中的图书编号此处为1800067256
title: 书名此处为Java : an introduction to problem solving & programming = Java : 程序设计与问题解决/ Walter Savitch著.表示该图书的书名是Java : 程序设计与问题解决作者是Walter Savitch
itemCount: 图书总数此处为8表示该图书馆系统中该图书的总数
circCount: 图书当前在借数量此处也为8表示该图书当前在借数量为8
pub_year: 出版年份此处为2006.表示该图书的出版年份是2006年
classno: 分类号此处为TP312JA可能是用于图书分类的一个标识
publisher: 出版商此处为Posts & Telecom Press表示该图书的出版商是Posts & Telecom Press
holdings: 持有情况此处为空字符串可能是用于记录该图书的其他持有情况
_id: 记录ID此处为544237可能是用于记录该图书的唯一标识
*/

@ -0,0 +1,12 @@
package cn.wustlinghang.mywust.data.library.origin;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class CurrentLoanBook extends BaseLoanBook {
private String dueDate;
}

@ -0,0 +1,12 @@
package cn.wustlinghang.mywust.data.library.origin;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public class HistoryLoanBook extends BaseLoanBook {
private String returnDate;
}

@ -0,0 +1,51 @@
package cn.wustlinghang.mywust.data.library.parsed;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
/**
* 书籍详情
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BookDetail {
private String title;
private String author;
private String isbn;
/**
* 作者介绍
*/
private String authorDescribe;
/**
* 目录
*/
private String catalog;
/**
* 封面url
*/
private String coverUrl;
/**
* 图书简要
*/
private String summary;
/**
* 图书介绍
*/
private String introduction;
/**
* 书籍详细信息因为图书馆系统奇葩的中文不定key因此将这些信息放入key-value对中需要者自取
*/
Map<String, String> extraInfoMap;
}

@ -0,0 +1,56 @@
package cn.wustlinghang.mywust.data.library.parsed;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 馆藏信息单个
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class BookHolding {
@JsonProperty("callNo")
private String callNumber;
/**
* 馆藏总数
*/
private int itemsCount;
/**
* 可借数
*/
private int itemsAvailable;
/**
* 条形码
*/
private String barCode;
/**
* 所属馆藏地
*/
private String location;
/**
* 临时馆藏地
*/
private String tempLocation;
/**
* 卷年期
*/
@JsonProperty("vol")
private String volume;
/**
* 馆名总馆等等
*/
private String library;
/**
* 状态文本
*/
private String status;
}

@ -0,0 +1,69 @@
package cn.wustlinghang.mywust.data.library.parsed;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class BookSearchResult {
private String bibId;
private List<String> holdingTypes;
private String author;
private List<String> callNumber;
/**
* 文献类型
*/
private String docType;
private String groupId;
private String isbn;
/**
* 图书馆系统中的图书编号
*/
private String bibNo;
private String title;
/**
* 图书总数
*/
private int itemCount;
/**
* 在借数量
*/
private int circCount;
private String pubYear;
private String classNumber;
private String publisher;
private List<BookHolding> holdings;
}
/*
bibId: 图书馆系统中的图书ID用于唯一标识一本图书
holdingTypes: 图书的持有类型此处为print表示该图书以纸质形式持有
author: 作者此处为Walter Savitch著表示该图书的作者是Walter Savitch
callno: 索书号此处为["TP312JA/E26=4/1","TP312JA/E26=4/2"]表示该图书的索书号是TP312JA/E26=4/1和TP312JA/E26=4/2
docType: 文献类型此处为doc.02表示该图书的文献类型为doc.02
groupId: 分组ID此处为1e24652f1d98f0586dc6468136f8eba6可能是用于图书分类的一个标识
isbn: ISBN号此处为7115152888 (v. 1)表示该图书的ISBN号是7115152888其中(v. 1)可能表示版本号
bibNo: 图书馆系统中的图书编号此处为1800067256
title: 书名此处为Java : an introduction to problem solving & programming = Java : 程序设计与问题解决/ Walter Savitch著.表示该图书的书名是Java : 程序设计与问题解决作者是Walter Savitch
itemCount: 图书总数此处为8表示该图书馆系统中该图书的总数
circCount: 图书当前在借数量此处也为8表示该图书当前在借数量为8
pub_year: 出版年份此处为2006.表示该图书的出版年份是2006年
classno: 分类号此处为TP312JA可能是用于图书分类的一个标识
publisher: 出版商此处为Posts & Telecom Press表示该图书的出版商是Posts & Telecom Press
holdings: 持有情况此处为空字符串可能是用于记录该图书的其他持有情况
_id: 记录ID此处为544237可能是用于记录该图书的唯一标识
*/

@ -1,6 +1,6 @@
package cn.linghang.mywust.data.physics;
package cn.wustlinghang.mywust.data.physics;
import cn.linghang.mywust.data.global.Course;
import cn.wustlinghang.mywust.data.global.Course;
import lombok.Getter;
import lombok.Setter;

@ -1,4 +1,4 @@
package cn.linghang.mywust.data.undergrad;
package cn.wustlinghang.mywust.data.undergrad;
import lombok.AllArgsConstructor;
import lombok.Data;

@ -1,4 +1,4 @@
package cn.linghang.mywust.exception;
package cn.wustlinghang.mywust.exception;
public class ApiException extends BasicException {
private final Code code;
@ -99,6 +99,16 @@ public class ApiException extends BasicException {
*/
UNI_LOGIN_NEED_TFA(100107, "统一认证登录: 用户账号需要TFA二步验证"),
/**
* 专属选课时间段账号被禁用
*/
UNDERGRAD_BANNED_IN_EXCLUSIVE_TIME(100108, "本科生登录:专属选课时间段账号被禁用"),
/**
* 用户名信息不存在新生信息未录入或者老生删档
*/
UNDERGRAD_USERINFO_NOT_EXISTS(100109, "本科生登录:用户名信息(新生信息未录入或者老生删档)"),
// --------------------------------
// 共有异常码:cookie无效
@ -128,6 +138,11 @@ public class ApiException extends BasicException {
*/
PHYSICS_PASSWORD_WRONG(130100, "物理实验系统登录: 密码错误"),
/**
* 物理实验系统用户不存在于当前学期
*/
PHYSICS_NOT_CURRENT_TERM(130101, "物理实验系统登录: 当前用户不存在于当前学期"),
// --------------------------------
// 研究生API异常代码
@ -136,6 +151,10 @@ public class ApiException extends BasicException {
*/
GRADUATE_PASSWORD_WRONG(140100, "研究生登录: 密码错误"),
/**
* 研究生验证码错误
*/
GRADUATE_CAPTCHA_WRONG(140101, "研究生登录: 验证码错误"),
// --------------------------------
// 图书馆API异常代码

@ -1,4 +1,4 @@
package cn.linghang.mywust.exception;
package cn.wustlinghang.mywust.exception;
public class BasicException extends Exception {
public BasicException() {

@ -1,4 +1,4 @@
package cn.linghang.mywust.exception;
package cn.wustlinghang.mywust.exception;
import java.util.StringJoiner;

@ -4,21 +4,52 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mywust</artifactId>
<groupId>cn.linghang</groupId>
<groupId>cn.wustlinghang.mywust</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mywust-core</artifactId>
<name>${project.artifactId}</name>
<description>The API encapsulations of WUST's official web service. Module `${project.artifactId}`</description>
<url>https://github.com/LingHangStudio/mywust</url>
<scm>
<url>https://github.com/LingHangStudio/mywust</url>
<connection>scm:git:https://github.com/LingHangStudio/mywust.git</connection>
<developerConnection>scm:git:https://github.com/LingHangStudio/mywust.git</developerConnection>
<tag>${project.parent.version}</tag>
</scm>
<developers>
<developer>
<id>lensfrex</id>
<name>lensfrex</name>
<email>lensferno@outlook.com</email>
<url>https://github.com/lensferno</url>
<organization>wustlinghang</organization>
<organizationUrl>https://github.com/LingHangStudio</organizationUrl>
<timezone>+8</timezone>
</developer>
</developers>
<licenses>
<license>
<name>MIT License</name>
<url>https://mit-license.org/</url>
</license>
</licenses>
<dependencies>
<dependency>
<groupId>cn.linghang</groupId>
<groupId>cn.wustlinghang.mywust</groupId>
<artifactId>mywust-network</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.linghang</groupId>
<groupId>cn.wustlinghang.mywust</groupId>
<artifactId>mywust-util</artifactId>
<version>${project.parent.version}</version>
</dependency>
@ -37,7 +68,7 @@
</dependency>
<dependency>
<groupId>cn.linghang</groupId>
<groupId>cn.wustlinghang.mywust</groupId>
<artifactId>mywust-common</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
@ -45,13 +76,13 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.14.0-rc1</version>
<version>${jackson.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.0-rc1</version>
<version>${jackson.version}</version>
<scope>compile</scope>
</dependency>
@ -69,6 +100,7 @@
<slf4j.version>2.0.3</slf4j.version>
<jsoup.version>1.15.3</jsoup.version>
<hutool.version>5.8.12</hutool.version>
<hutool.version>5.8.22</hutool.version>
<jackson.version>2.15.2</jackson.version>
</properties>
</project>

@ -1,7 +0,0 @@
package cn.linghang.mywust.core.parser;
import cn.linghang.mywust.exception.ParseException;
public interface Parser<T> {
public T parse(String html) throws ParseException;
}

@ -1,40 +0,0 @@
package cn.linghang.mywust.core.request.factory.library.request;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
@Data
public class SearchRequest {
private final List<Object> filterFieldList = new ArrayList<>();
private final String collapseField = "groupId";
private final String sortType = "desc";
private final String indexName = "idx.opac";
private final String sortField = "relevance";
private final List<QueryFieldListItem> queryFieldList = new ArrayList<>(1);
private int pageSize;
private int page;
public SearchRequest(String keyWord, int pageSize, int page) {
this.pageSize = pageSize;
this.page = page;
this.queryFieldList.add(new QueryFieldListItem(keyWord));
}
@Data
public static class QueryFieldListItem {
private final String field = "all";
private final String operator = "*";
private final int logic = 0;
private final List<String> values = new ArrayList<>(1);
public QueryFieldListItem(String keyWord) {
values.add(keyWord);
}
}
}

@ -1,9 +0,0 @@
package cn.linghang.mywust.core.request.service.captcha.solver;
import cn.linghang.mywust.captcha.SolvedImageCaptcha;
import cn.linghang.mywust.captcha.UnsolvedImageCaptcha;
import cn.linghang.mywust.exception.ApiException;
public interface CaptchaSolver {
SolvedImageCaptcha solve(UnsolvedImageCaptcha unsolvedImageCaptcha) throws ApiException;
}

@ -1,66 +0,0 @@
package cn.linghang.mywust.core.request.service.library;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.linghang.mywust.network.Requester;
import cn.linghang.mywust.network.entitys.HttpRequest;
import cn.linghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
/**
* 图书馆相关接口由于返回的数据都是json特别好解析所以这里的数据获取到了之后可以直接拿来用自己来解析
*/
public class LibraryApiService extends LibraryApiServiceBase {
public LibraryApiService(Requester requester) {
super(requester);
}
public String search(String keyword, int page, int pageSize) throws ApiException, IOException {
HttpRequest request = LibraryRequestFactory.bookSearchRequest(keyword, page, pageSize);
HttpResponse response = requester.post(request);
checkResponse(response);
return response.getStringBody();
}
public String getBookDetail(String bookId) throws ApiException, IOException {
HttpRequest request = LibraryRequestFactory.bookInfoRequest(bookId);
HttpResponse response = requester.get(request);
checkResponse(response);
return response.getStringBody();
}
public String getBookCoverImageUrl(String isbn) throws ApiException, IOException {
HttpRequest request = LibraryRequestFactory.bookCoverImageUrlRequest(isbn);
HttpResponse response = requester.get(request);
checkResponse(response);
return response.getStringBody();
}
public String getOverdueSoon(String cookie) throws ApiException, IOException {
HttpRequest request = LibraryRequestFactory.overdueSoonRequest(cookie);
HttpResponse response = requester.get(request);
checkResponse(response);
return response.getStringBody();
}
public String getCurrentLoan(String cookie) throws ApiException, IOException {
HttpRequest request = LibraryRequestFactory.currentLoanRequest(cookie);
HttpResponse response = requester.get(request);
checkResponse(response);
return response.getStringBody();
}
public String getLoanHistory(String cookie) throws ApiException, IOException {
HttpRequest request = LibraryRequestFactory.loanHistoryRequest(cookie);
HttpResponse response = requester.get(request);
checkResponse(response);
return response.getStringBody();
}
}

@ -1,20 +0,0 @@
package cn.linghang.mywust.core.request.service.library;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.network.Requester;
import cn.linghang.mywust.network.entitys.HttpResponse;
public abstract class LibraryApiServiceBase {
protected final Requester requester;
public LibraryApiServiceBase(Requester requester) {
this.requester = requester;
}
public void checkResponse(HttpResponse response) throws ApiException {
// 检查响应是否正确
if (response.getStatusCode() != 200) {
throw new ApiException(ApiException.Code.COOKIE_INVALID);
}
}
}

@ -1,32 +0,0 @@
package cn.linghang.mywust.core.util;
import java.nio.charset.StandardCharsets;
/**
* 专属于bkjx本科教学系统服务的工具类
*/
public class BkjxUtil {
// 在“Bkjx”系统里边如果收到的响应开头是这个的话多半是cookie无效了,需要重新登录获取cookie
private static final byte[] LOGIN_MESSAGE_RESPONSE_FINGER = "<script".getBytes(StandardCharsets.UTF_8);
/**
* <p>通过粗暴地比较响应字节前几个字符是否为登录跳转特征字符判断是否需要重新登录</p>
* <p>对于null对象一律认为不需要</p>
*
* @param response 响应的字节
* @return 是否需要重新登录
*/
public static boolean hasLoginFinger(byte[] response) {
if (response == null) {
return false;
}
for (int i = 0; i < LOGIN_MESSAGE_RESPONSE_FINGER.length; i++) {
if (LOGIN_MESSAGE_RESPONSE_FINGER[i] != response[i]) {
return false;
}
}
return true;
}
}

@ -1,4 +1,4 @@
package cn.linghang.mywust.core.api;
package cn.wustlinghang.mywust.core.api;
import java.util.Collections;
import java.util.HashMap;

@ -1,4 +1,4 @@
package cn.linghang.mywust.core.api;
package cn.wustlinghang.mywust.core.api;
public class GraduateUrls {
public static final String GRADUATE_CAPTCHA_API = "http://59.68.177.189/pyxx/PageTemplate/NsoftPage/yzm/createyzm.aspx";

@ -1,19 +1,23 @@
package cn.linghang.mywust.core.api;
package cn.wustlinghang.mywust.core.api;
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";
public static final String LIBRARY_COOKIE_TEST_URL = "https://libsys.wust.edu.cn/meta-local/opac/users/info";
// 用违章记录信息api地址作为测试url(大部分人应该没有违章吧 :)
public static final String LIBRARY_COOKIE_TEST_URL = "https://libsys.wust.edu.cn/meta-local/opac/users/volts";
public static final String LIBRARY_ACCOUNT_STATUS_API = "https://libsys.wust.edu.cn/meta-local/opac/users/stats";
public static final String LIBRARY_CURRENT_LOAN_API = "https://libsys.wust.edu.cn/meta-local/opac/users/loans?page=1&pageSize=100";
public static final String LIBRARY_LOAN_HISTORY_API = "https://libsys.wust.edu.cn/meta-local/opac/users/loan_hists?page=1&pageSize=100";
public static final String LIBRARY_OVERDUE_SOON_API = "https://libsys.wust.edu.cn/meta-local/opac/users/overdue_soon";
public static final String LIBRARY_CURRENT_LOAN_API = "https://libsys.wust.edu.cn/meta-local/opac/users/loans?page=%d&pageSize=%d";
public static final String LIBRARY_LOAN_HISTORY_API = "https://libsys.wust.edu.cn/meta-local/opac/users/loan_hists?page=%d&pageSize=%d";
public static final String LIBRARY_OVERDUE_SOON_API = "https://libsys.wust.edu.cn/meta-local/opac/users/overdue_soon?page=%d&pageSize=%d";
public static final String LIBRARY_BOOK_INFO_API = "https://libsys.wust.edu.cn/meta-local/opac/bibs/%s/infos";
public static final String LIBRARY_BOOK_DOUBAN_INFO_API = "https://libsys.wust.edu.cn/meta-local/opac/third_api/douban/%s/info";
public static final String LIBRARY_BOOK_CONTENT_API = "https://libsys.wust.edu.cn/meta-local/opac/bibs/%s/quoteds/quoted.caj-cd/content";
public static final String LIBRARY_BOOK_HOLDING_API = "https://libsys.wust.edu.cn/meta-local/opac/bibs/%s/holdings";
public static final String LIBRARY_BOOK_COVER_IMAGE_API = "https://libsys.wust.edu.cn/meta-local/opac/search/extend/";

@ -1,4 +1,4 @@
package cn.linghang.mywust.core.api;
package cn.wustlinghang.mywust.core.api;
public class PhysicsSystemUrls {
public static final String PHYSICS_LOGIN_INDEX = "http://wlsy.wust.edu.cn/Page/BI/BI000.aspx";

@ -1,4 +1,4 @@
package cn.linghang.mywust.core.api;
package cn.wustlinghang.mywust.core.api;
import lombok.Getter;

@ -1,4 +1,4 @@
package cn.linghang.mywust.core.api;
package cn.wustlinghang.mywust.core.api;
public class UnionAuthUrls {
/**

@ -1,7 +1,7 @@
package cn.linghang.mywust.core.parser;
package cn.wustlinghang.mywust.core.parser;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.data.global.Classroom;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.data.global.Classroom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ -0,0 +1,7 @@
package cn.wustlinghang.mywust.core.parser;
import cn.wustlinghang.mywust.exception.ParseException;
public interface Parser<T> {
public T parse(String html) throws ParseException;
}

@ -1,9 +1,9 @@
package cn.linghang.mywust.core.parser.graduate;
package cn.wustlinghang.mywust.core.parser.graduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.data.global.Classroom;
import cn.linghang.mywust.data.global.Course;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.data.global.Classroom;
import cn.wustlinghang.mywust.data.global.Course;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

@ -1,8 +1,8 @@
package cn.linghang.mywust.core.parser.graduate;
package cn.wustlinghang.mywust.core.parser.graduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.data.global.Score;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.data.global.Score;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

@ -1,9 +1,9 @@
package cn.linghang.mywust.core.parser.graduate;
package cn.wustlinghang.mywust.core.parser.graduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.util.JsoupUtil;
import cn.linghang.mywust.data.global.StudentInfo;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.core.util.JsoupUtil;
import cn.wustlinghang.mywust.data.global.StudentInfo;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;

@ -1,17 +1,14 @@
package cn.linghang.mywust.core.parser.graduate;
package cn.wustlinghang.mywust.core.parser.graduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.util.JsoupUtil;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.core.util.JsoupUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
public class GraduateTrainingPlanPageParser implements Parser<String> {
private static final String HTML_PREFIX = "<!DOCTYPE html><html lang=\"zh\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>培养计划</title></head><body>";
private static final String HTML_SUFFIX = "</body></html>";
@Override
public String parse(String html) throws ParseException {
try {
@ -25,7 +22,7 @@ public class GraduateTrainingPlanPageParser implements Parser<String> {
String table = JsoupUtil.getOuterHtml(fullTable.getElementById("_ctl0_MainWork_dgData"));
String foot = JsoupUtil.getOuterHtml(fullTable.getElementById("Table4"));
return HTML_PREFIX + head + table + foot + HTML_SUFFIX;
return head + table + foot;
}catch (Exception e) {
// 解析失败就直接返回原网页展示
return html;

@ -1,10 +1,10 @@
package cn.linghang.mywust.core.parser.physics;
package cn.wustlinghang.mywust.core.parser.physics;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.HuangjiahuClassroomNameParser;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.data.global.Classroom;
import cn.linghang.mywust.data.physics.PhysicsCourse;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.HuangjiahuClassroomNameParser;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.data.global.Classroom;
import cn.wustlinghang.mywust.data.physics.PhysicsCourse;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;

@ -1,7 +1,7 @@
package cn.linghang.mywust.core.parser.physics;
package cn.wustlinghang.mywust.core.parser.physics;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

@ -1,8 +1,8 @@
package cn.linghang.mywust.core.parser.physics;
package cn.wustlinghang.mywust.core.parser.physics;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.util.JsoupUtil;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.core.util.JsoupUtil;
import lombok.Data;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

@ -1,9 +1,9 @@
package cn.linghang.mywust.core.parser.physics;
package cn.wustlinghang.mywust.core.parser.physics;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.util.JsoupUtil;
import cn.linghang.mywust.data.global.Score;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.core.util.JsoupUtil;
import cn.wustlinghang.mywust.data.global.Score;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.parser.undergraduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.util.JsoupUtil;
import cn.linghang.mywust.data.global.Classroom;
import cn.linghang.mywust.data.global.Course;
import cn.linghang.mywust.util.StringUtil;
package cn.wustlinghang.mywust.core.parser.undergraduate;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.core.util.JsoupUtil;
import cn.wustlinghang.mywust.data.global.Classroom;
import cn.wustlinghang.mywust.data.global.Course;
import cn.wustlinghang.mywust.util.StringUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

@ -1,7 +1,7 @@
package cn.linghang.mywust.core.parser.undergraduate;
package cn.wustlinghang.mywust.core.parser.undergraduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

@ -1,7 +1,7 @@
package cn.linghang.mywust.core.parser.undergraduate;
package cn.wustlinghang.mywust.core.parser.undergraduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;

@ -1,9 +1,9 @@
package cn.linghang.mywust.core.parser.undergraduate;
package cn.wustlinghang.mywust.core.parser.undergraduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.util.JsoupUtil;
import cn.linghang.mywust.data.undergrad.ExamDelayApplication;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.core.util.JsoupUtil;
import cn.wustlinghang.mywust.data.undergrad.ExamDelayApplication;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;

@ -1,9 +1,9 @@
package cn.linghang.mywust.core.parser.undergraduate;
package cn.wustlinghang.mywust.core.parser.undergraduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.util.JsoupUtil;
import cn.linghang.mywust.data.global.Score;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.core.util.JsoupUtil;
import cn.wustlinghang.mywust.data.global.Score;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

@ -1,9 +1,9 @@
package cn.linghang.mywust.core.parser.undergraduate;
package cn.wustlinghang.mywust.core.parser.undergraduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.util.JsoupUtil;
import cn.linghang.mywust.data.global.StudentInfo;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.core.util.JsoupUtil;
import cn.wustlinghang.mywust.data.global.StudentInfo;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

@ -1,7 +1,7 @@
package cn.linghang.mywust.core.parser.undergraduate;
package cn.wustlinghang.mywust.core.parser.undergraduate;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;

@ -1,9 +1,9 @@
package cn.linghang.mywust.core.parser.undergraduate.global;
package cn.wustlinghang.mywust.core.parser.undergraduate.global;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.data.global.Classroom;
import cn.linghang.mywust.data.global.Course;
import cn.linghang.mywust.util.StringUtil;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.data.global.Classroom;
import cn.wustlinghang.mywust.data.global.Course;
import cn.wustlinghang.mywust.util.StringUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

@ -1,8 +1,8 @@
package cn.linghang.mywust.core.parser.undergraduate.global;
package cn.wustlinghang.mywust.core.parser.undergraduate.global;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.data.global.Course;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.data.global.Course;
import java.util.List;
import java.util.regex.Pattern;

@ -1,8 +1,8 @@
package cn.linghang.mywust.core.parser.undergraduate.global;
package cn.wustlinghang.mywust.core.parser.undergraduate.global;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.data.global.Course;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.Parser;
import cn.wustlinghang.mywust.data.global.Course;
import java.util.List;
import java.util.regex.Pattern;

@ -1,9 +1,9 @@
package cn.linghang.mywust.core.request.factory.auth;
package cn.wustlinghang.mywust.core.request.factory.auth;
import cn.linghang.mywust.core.api.UnionAuthUrls;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.network.entitys.HttpRequest;
import cn.linghang.mywust.util.StringUtil;
import cn.wustlinghang.mywust.core.api.UnionAuthUrls;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.util.StringUtil;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.factory.graduate;
import cn.linghang.mywust.captcha.SolvedImageCaptcha;
import cn.linghang.mywust.core.api.GraduateUrls;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.core.util.PageFormExtractor;
import cn.linghang.mywust.network.entitys.HttpRequest;
import cn.linghang.mywust.util.StringUtil;
package cn.wustlinghang.mywust.core.request.factory.graduate;
import cn.wustlinghang.mywust.captcha.SolvedImageCaptcha;
import cn.wustlinghang.mywust.core.api.GraduateUrls;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.core.util.PageFormExtractor;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.util.StringUtil;
import lombok.Builder;
import lombok.Data;

@ -1,16 +1,17 @@
package cn.linghang.mywust.core.request.factory.library;
package cn.wustlinghang.mywust.core.request.factory.library;
import cn.hutool.core.util.URLUtil;
import cn.linghang.mywust.core.api.LibraryUrls;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.core.request.factory.library.request.SearchRequest;
import cn.linghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.core.api.LibraryUrls;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.data.library.origin.BookSearchRequest;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.StringJoiner;
@Slf4j
public class LibraryRequestFactory extends RequestFactory {
private static final ObjectMapper objectMapper = new ObjectMapper();
@ -25,10 +26,10 @@ public class LibraryRequestFactory extends RequestFactory {
}
public static HttpRequest bookSearchRequest(String keyword, int page, int pageSize) {
return bookSearchRequest(new SearchRequest(keyword, pageSize, page));
return bookSearchRequest(new BookSearchRequest(keyword, pageSize, page));
}
public static HttpRequest bookSearchRequest(SearchRequest request) {
public static HttpRequest bookSearchRequest(BookSearchRequest request) {
return makeHttpRequest(LibraryUrls.LIBRARY_SEARCH_API, json(request))
.addHeaders("Content-Type", "application/json");
}
@ -37,16 +38,16 @@ public class LibraryRequestFactory extends RequestFactory {
return makeHttpRequest(LibraryUrls.LIBRARY_ACCOUNT_STATUS_API, null, cookie);
}
public static HttpRequest currentLoanRequest(String cookie) {
return makeHttpRequest(LibraryUrls.LIBRARY_CURRENT_LOAN_API, null, cookie);
public static HttpRequest currentLoanRequest(String cookie, int page, int pageSize) {
return makeHttpRequest(String.format(LibraryUrls.LIBRARY_CURRENT_LOAN_API, page, pageSize), null, cookie);
}
public static HttpRequest loanHistoryRequest(String cookie) {
return makeHttpRequest(LibraryUrls.LIBRARY_LOAN_HISTORY_API, null, cookie);
public static HttpRequest loanHistoryRequest(String cookie, int page, int pageSize) {
return makeHttpRequest(String.format(LibraryUrls.LIBRARY_LOAN_HISTORY_API, page, pageSize), null, cookie);
}
public static HttpRequest overdueSoonRequest(String cookie) {
return makeHttpRequest(LibraryUrls.LIBRARY_OVERDUE_SOON_API, null, cookie);
public static HttpRequest overdueSoonRequest(String cookie, int page, int pageSize) {
return makeHttpRequest(String.format(LibraryUrls.LIBRARY_OVERDUE_SOON_API, page, pageSize), null, cookie);
}
public static HttpRequest bookInfoRequest(String bookId) {
@ -54,6 +55,21 @@ public class LibraryRequestFactory extends RequestFactory {
return makeHttpRequest(url, (byte[]) null);
}
public static HttpRequest bookDoubanInfoRequest(String isbn) {
String url = String.format(LibraryUrls.LIBRARY_BOOK_DOUBAN_INFO_API, isbn);
return makeHttpRequest(url, (byte[]) null);
}
public static HttpRequest bookContentRequest(String id) {
String url = String.format(LibraryUrls.LIBRARY_BOOK_CONTENT_API, id);
return makeHttpRequest(url, (byte[]) null);
}
public static HttpRequest bookHoldingRequest(String bookId) {
String url = String.format(LibraryUrls.LIBRARY_BOOK_HOLDING_API, bookId);
return makeHttpRequest(url, (byte[]) null);
}
public static HttpRequest bookCoverImageUrlRequest(List<String> isbn) {
StringJoiner joiner = new StringJoiner("%2C", LibraryUrls.LIBRARY_BOOK_COVER_IMAGE_API, "");
isbn.forEach(joiner::add);
@ -68,7 +84,8 @@ public class LibraryRequestFactory extends RequestFactory {
private static String json(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException ignored) {
} catch (JsonProcessingException e) {
log.error("生成json时出现不应出现的异常:", e);
return "";
}
}

@ -1,10 +1,10 @@
package cn.linghang.mywust.core.request.factory.physics;
package cn.wustlinghang.mywust.core.request.factory.physics;
import cn.linghang.mywust.core.api.PhysicsSystemUrls;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.core.util.PageFormExtractor;
import cn.linghang.mywust.network.entitys.HttpRequest;
import cn.linghang.mywust.util.StringUtil;
import cn.wustlinghang.mywust.core.api.PhysicsSystemUrls;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.core.util.PageFormExtractor;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.util.StringUtil;
import java.util.HashMap;
import java.util.Map;
@ -31,6 +31,10 @@ public class PhysicsSystemRequestFactory extends RequestFactory {
return makeHttpRequest(redirect, null, cookies);
}
public static HttpRequest physicsSystemIndexRequest(String cookies) {
return makeHttpRequest(PhysicsSystemUrls.PHYSICS_SYSTEM_INDEX_URL, null, cookies);
}
public static HttpRequest physicsCourseRequest(String cookies) {
return makeHttpRequest(PhysicsSystemUrls.PHYSICS_COURSE_API, null, cookies);
}

@ -1,17 +1,16 @@
package cn.linghang.mywust.core.request.factory.undergrade;
package cn.wustlinghang.mywust.core.request.factory.undergrade;
import cn.linghang.mywust.core.api.UndergradUrls;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.data.global.Campus;
import cn.linghang.mywust.network.entitys.FormBodyBuilder;
import cn.linghang.mywust.network.entitys.HttpRequest;
import cn.linghang.mywust.util.StringUtil;
import cn.wustlinghang.mywust.core.api.UndergradUrls;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.data.global.Campus;
import cn.wustlinghang.mywust.network.entitys.FormBodyBuilder;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.util.StringUtil;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class BkjxRequestFactory extends RequestFactory {
public static HttpRequest sessionCookieRequest(String serviceTicket) {

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.factory.undergrade.global;
package cn.wustlinghang.mywust.core.request.factory.undergrade.global;
import cn.linghang.mywust.core.api.ConstantParams;
import cn.linghang.mywust.core.api.UndergradUrls;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.linghang.mywust.network.entitys.FormBodyBuilder;
import cn.linghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.core.api.ConstantParams;
import cn.wustlinghang.mywust.core.api.UndergradUrls;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.network.entitys.FormBodyBuilder;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
public class BkjxAllCourseRequestFactory extends BkjxRequestFactory {
public static HttpRequest classroomCoursePageRequest(String cookies, String term, String timeMode, String collegeId, String campusId, String buildingId, String classroomName) {
@ -54,7 +54,7 @@ public class BkjxAllCourseRequestFactory extends BkjxRequestFactory {
.add("kbjcmsid", timeMode == null ? ConstantParams.DEFAULT_TIME_MODEL : timeMode)
// 上课学院,虽然能获取到,但是不符合预期的功能,得到的结果是这个学院上的课,而不是这个学院开的课
.add("skyx", "")
// 开课学院应该在这里指定,但是直接用学院id是获取不到的,只能用学院下级的id来获取,相关参数详见cn.linghang.mywust.core.api.ConstantParams
// 开课学院应该在这里指定,但是直接用学院id是获取不到的,只能用学院下级的id来获取,相关参数详见cn.wustlinghang.mywust.core.api.ConstantParams
.add("kkyx", subCollegeId)
.add("kcmc", courseName)
.add("zzdKcSX", "")

@ -1,16 +1,17 @@
package cn.linghang.mywust.core.request.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.exception.ApiException;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
import cn.linghang.mywust.core.request.service.captcha.solver.CaptchaSolver;
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;
package cn.wustlinghang.mywust.core.request.service.auth;
import cn.wustlinghang.mywust.captcha.SolvedImageCaptcha;
import cn.wustlinghang.mywust.captcha.UnsolvedImageCaptcha;
import cn.wustlinghang.mywust.core.api.GraduateUrls;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
import cn.wustlinghang.mywust.core.request.service.captcha.solver.CaptchaSolver;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import java.awt.*;
@ -19,6 +20,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@Slf4j
public class GraduateLogin {
private final Requester requester;
@ -49,18 +51,43 @@ public class GraduateLogin {
SolvedImageCaptcha solvedImageCaptcha = captchaSolver.solve(unsolvedImageCaptcha);
// 进行登录
HttpRequest loginRequest = GraduateRequestFactory.loginRequest(username, password, loginIndexResponse.getStringBody(), solvedImageCaptcha);
String loginIndexHtml = loginIndexResponse.getStringBody();
HttpRequest loginRequest = GraduateRequestFactory.loginRequest(username, password, loginIndexHtml, solvedImageCaptcha);
HttpResponse loginResponse = requester.post(loginRequest, option);
// 登陆成功,应该会是302跳转,不是的话多半是认证错误
if (loginResponse.getStatusCode() != HttpResponse.HTTP_REDIRECT_302) {
throw new ApiException(ApiException.Code.GRADUATE_PASSWORD_WRONG);
String responseHtml = loginResponse.getStringBody();
if (responseHtml.contains("验证码错误")) {
throw new ApiException(ApiException.Code.GRADUATE_CAPTCHA_WRONG);
} else if (responseHtml.contains("密码错误") || responseHtml.contains("用户名不存在")) {
throw new ApiException(ApiException.Code.GRADUATE_PASSWORD_WRONG);
} else {
throw new ApiException(ApiException.Code.UNKNOWN_EXCEPTION);
}
}
// 使用首页第一次访问得到的cookie来作为登录cookie
return loginCookie;
}
public String getLoginCookie(String username, String password, int maxRetryTimes, RequestClientOption option)
throws IOException, ApiException {
for (int i = 0; i < maxRetryTimes; i++) {
try {
return getLoginCookie(username, password, option);
} catch (ApiException e) {
if (e.getCode() != ApiException.Code.GRADUATE_CAPTCHA_WRONG) {
throw e;
} else {
log.info("[mywust]: Retrying login for {} time(s)", i);
}
}
}
return "";
}
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);

@ -1,13 +1,13 @@
package cn.linghang.mywust.core.request.service.auth;
package cn.wustlinghang.mywust.core.request.service.auth;
import cn.linghang.mywust.core.api.LibraryUrls;
import cn.linghang.mywust.core.api.UnionAuthUrls;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.library.LibraryRequestFactory;
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.wustlinghang.mywust.core.api.LibraryUrls;
import cn.wustlinghang.mywust.core.api.UnionAuthUrls;
import cn.wustlinghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
@ -30,10 +30,15 @@ public class LibraryLogin {
HttpResponse sessionResponse = requester.get(sessionRequest, requestOption);
String cookies = sessionResponse.getCookies();
// 请求一次首页
// 请求一次首页,这次获得的cookie才是真正的cookie
HttpRequest indexRequest = LibraryRequestFactory.indexRequest();
indexRequest.setCookies(cookies);
requester.get(indexRequest, requestOption);
HttpResponse indexResponse = requester.get(indexRequest, requestOption);
cookies = indexResponse.getCookies() != null ? indexResponse.getCookies() : cookies;
if (!checkCookie(cookies)) {
throw new ApiException(ApiException.Code.COOKIE_INVALID);
}
return cookies;
}

@ -1,13 +1,13 @@
package cn.linghang.mywust.core.request.service.auth;
package cn.wustlinghang.mywust.core.request.service.auth;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.physics.PhysicsIndexPageParser;
import cn.linghang.mywust.core.request.factory.physics.PhysicsSystemRequestFactory;
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.wustlinghang.mywust.core.parser.physics.PhysicsIndexPageParser;
import cn.wustlinghang.mywust.core.request.factory.physics.PhysicsSystemRequestFactory;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -34,7 +34,14 @@ public class PhysicsLogin {
HttpRequest loginCookieRequest = PhysicsSystemRequestFactory.loginCookiesRequest(username, password, loginIndex);
HttpResponse loginCookieResponse = requester.post(loginCookieRequest, requestClientOption);
if (loginCookieResponse.getStatusCode() != HttpResponse.HTTP_REDIRECT_302) {
throw new ApiException(ApiException.Code.PHYSICS_PASSWORD_WRONG);
String responseHtml = loginCookieResponse.getStringBody();
if (responseHtml.contains("该用户不存在于当前学期")){
throw new ApiException(ApiException.Code.PHYSICS_NOT_CURRENT_TERM);
} else if (responseHtml.contains("用户名或者密码有误")) {
throw new ApiException(ApiException.Code.PHYSICS_PASSWORD_WRONG);
} else {
throw new ApiException(ApiException.Code.UNKNOWN_EXCEPTION);
}
}
String loginCookies = loginCookieResponse.getCookies();
@ -55,7 +62,7 @@ public class PhysicsLogin {
String redirect = physicsIndexPageParser.parse(indexHtml);
HttpRequest systemIndexRequest = PhysicsSystemRequestFactory.physicsSystemIndexRequest(redirect, loginCookies);
requestClientOption.setFallowUrlRedirect(true);
requestClientOption.setFollowUrlRedirect(true);
HttpResponse response = requester.get(systemIndexRequest, requestClientOption);
if (response.getStatusCode() != HttpResponse.HTTP_OK) {
throw new ApiException(ApiException.Code.COOKIE_INVALID);
@ -63,4 +70,11 @@ public class PhysicsLogin {
return loginCookies;
}
public boolean checkCookie(String cookie, RequestClientOption option) throws IOException {
HttpRequest testRequest = PhysicsSystemRequestFactory.physicsSystemIndexRequest(cookie);
HttpResponse testResponse = requester.get(testRequest, option);
return testResponse.getStatusCode() != HttpResponse.HTTP_REDIRECT_302;
}
}

@ -1,14 +1,14 @@
package cn.linghang.mywust.core.request.service.auth;
import cn.linghang.mywust.core.api.UndergradUrls;
import cn.linghang.mywust.core.api.UnionAuthUrls;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.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;
package cn.wustlinghang.mywust.core.request.service.auth;
import cn.wustlinghang.mywust.core.api.UndergradUrls;
import cn.wustlinghang.mywust.core.api.UnionAuthUrls;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import cn.wustlinghang.mywust.util.PasswordEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -84,36 +84,46 @@ public class UndergraduateLogin {
}
private void checkCookie(String cookies, RequestClientOption requestOption) throws ApiException, IOException {
if (roughCheckCookieFail(cookies)) {
if (!roughCheckCookie(cookies)) {
log.error("[mywust]: Cookie粗查不通过:{}", cookies);
throw new ApiException(ApiException.Code.UNKNOWN_EXCEPTION, "登录获取的Cookie无效");
}
// 检查Cookie是否真正可用,同时请求一次任意接口使后续接口能够正确响应
// 拿到Cookie后调用的第一个接口有时候会产生302/301跳转到主页,需要再次调用才能正确响应
if (checkCookiesFail(cookies, requestOption)) {
if (!testCookie(cookies, requestOption)) {
log.warn("[mywust]: Cookie检查不通过:{}", cookies);
}
}
private boolean roughCheckCookieFail(String cookies) {
return cookies == null || !cookies.contains("JSESSIONID") || !cookies.contains("SERVERID");
private boolean roughCheckCookie(String cookies) {
return cookies != null && cookies.contains("JSESSIONID") && cookies.contains("SERVERID");
}
private static final int COOKIES_ERROR_RESPONSE_LENGTH =
("<script languge='javascript'>window.location.href='https://auth.wust.edu.cn/lyuapServer/login?service=http%3A%2F%2Fbkjx.wust.edu.cn%2Fjsxsd%2Fframework%2FblankPage.jsp'</script>")
.length();
public boolean checkCookiesFail(String cookies, RequestClientOption option) throws IOException {
public boolean testCookie(String cookies, RequestClientOption option) throws IOException, ApiException {
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;
// 空白页返回的是很短的几个换行符,优先判断响应长度,暂时定为8
if (testResponse.getBody().length < 8) {
return true;
}
String test = testResponse.getStringBody();
if (test.contains("script")) {
return false;
} else if (test.contains("禁用")) {
// 选课时间段
throw new ApiException(ApiException.Code.UNDERGRAD_BANNED_IN_EXCLUSIVE_TIME);
} else if (test.contains("不存在")) {
// 新生信息未录入/老生被删号
throw new ApiException(ApiException.Code.UNDERGRAD_USERINFO_NOT_EXISTS);
}
return true;
}
public boolean checkCookiesFail(String cookies) throws IOException {
return this.checkCookiesFail(cookies, null);
public boolean testCookie(String cookies) throws IOException, ApiException {
return this.testCookie(cookies, null);
}
}

@ -1,12 +1,12 @@
package cn.linghang.mywust.core.request.service.auth;
package cn.wustlinghang.mywust.core.request.service.auth;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.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 cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.auth.UnionAuthRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import cn.wustlinghang.mywust.util.PasswordEncoder;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ -0,0 +1,9 @@
package cn.wustlinghang.mywust.core.request.service.captcha.solver;
import cn.wustlinghang.mywust.captcha.SolvedImageCaptcha;
import cn.wustlinghang.mywust.captcha.UnsolvedImageCaptcha;
import cn.wustlinghang.mywust.exception.ApiException;
public interface CaptchaSolver {
SolvedImageCaptcha solve(UnsolvedImageCaptcha unsolvedImageCaptcha) throws ApiException;
}

@ -1,12 +1,12 @@
package cn.linghang.mywust.core.request.service.captcha.solver;
import cn.linghang.mywust.captcha.SolvedImageCaptcha;
import cn.linghang.mywust.captcha.UnsolvedImageCaptcha;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.network.Requester;
import cn.linghang.mywust.network.entitys.HttpRequest;
import cn.linghang.mywust.network.entitys.HttpResponse;
package cn.wustlinghang.mywust.core.request.service.captcha.solver;
import cn.wustlinghang.mywust.captcha.SolvedImageCaptcha;
import cn.wustlinghang.mywust.captcha.UnsolvedImageCaptcha;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Base64;

@ -1,14 +1,14 @@
package cn.linghang.mywust.core.request.service.captcha.solver;
import cn.linghang.mywust.captcha.SolvedImageCaptcha;
import cn.linghang.mywust.captcha.UnsolvedImageCaptcha;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.RequestFactory;
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;
package cn.wustlinghang.mywust.core.request.service.captcha.solver;
import cn.wustlinghang.mywust.captcha.SolvedImageCaptcha;
import cn.wustlinghang.mywust.captcha.UnsolvedImageCaptcha;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import cn.wustlinghang.mywust.util.StringUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.binary.Base64;

@ -1,12 +1,12 @@
package cn.linghang.mywust.core.request.service.graduate;
import cn.linghang.mywust.core.api.GraduateUrls;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.RequestFactory;
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;
package cn.wustlinghang.mywust.core.request.service.graduate;
import cn.wustlinghang.mywust.core.api.GraduateUrls;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.graduate;
package cn.wustlinghang.mywust.core.request.service.graduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
@ -23,6 +23,6 @@ public class GraduateCourseTableApiService extends GraduateApiServiceBase {
HttpResponse response = requester.get(request, option);
super.checkResponse(response);
return new String(response.getBody());
return response.getStringBody();
}
}

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.graduate;
package cn.wustlinghang.mywust.core.request.service.graduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
@ -22,6 +22,6 @@ public class GraduateScoreApiService extends GraduateApiServiceBase {
HttpResponse response = requester.get(request, option);
super.checkResponse(response);
return new String(response.getBody());
return response.getStringBody();
}
}

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.graduate;
package cn.wustlinghang.mywust.core.request.service.graduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
@ -22,6 +22,6 @@ public class GraduateStudentInfoApiService extends GraduateApiServiceBase {
HttpResponse response = requester.get(request, option);
super.checkResponse(response);
return new String(response.getBody());
return response.getStringBody();
}
}

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.graduate;
package cn.wustlinghang.mywust.core.request.service.graduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.graduate.GraduateRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
@ -22,6 +22,6 @@ public class GraduateTrainingPlanApiService extends GraduateApiServiceBase {
HttpResponse response = requester.get(request, option);
super.checkResponse(response);
return new String(response.getBody());
return response.getStringBody();
}
}

@ -0,0 +1,82 @@
package cn.wustlinghang.mywust.core.request.service.library;
import cn.wustlinghang.mywust.data.library.origin.BaseLoanBook;
import cn.wustlinghang.mywust.data.library.origin.BookSearchResult;
import cn.wustlinghang.mywust.data.library.origin.CurrentLoanBook;
import cn.wustlinghang.mywust.data.library.origin.HistoryLoanBook;
import cn.wustlinghang.mywust.data.library.parsed.BookHolding;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.util.List;
public abstract class BaseLibraryApiService {
protected static final ObjectMapper objectMapper = new ObjectMapper();
static {
objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
SimpleModule module = new SimpleModule();
module.addDeserializer(String.class, new SpecialStringDeserializer());
objectMapper.registerModule(module);
}
protected static final JavaType loanBookListType =
objectMapper.getTypeFactory().constructParametricType(List.class, BaseLoanBook.class);
protected static final JavaType historyLoanBookListType =
objectMapper.getTypeFactory().constructParametricType(List.class, HistoryLoanBook.class);
protected static final JavaType currentLoanBookListType =
objectMapper.getTypeFactory().constructParametricType(List.class, CurrentLoanBook.class);
protected static final JavaType bookSearchResultListType =
objectMapper.getTypeFactory().constructParametricType(List.class, BookSearchResult.class);
protected static final JavaType bookHoldingListType =
objectMapper.getTypeFactory().constructParametricType(List.class, BookHolding.class);
protected final Requester requester;
public BaseLibraryApiService(Requester requester) {
this.requester = requester;
}
public void checkResponse(HttpResponse response) throws ApiException {
// 检查响应是否正确
if (response.getStatusCode() != 200) {
throw new ApiException(ApiException.Code.COOKIE_INVALID);
}
}
}
/**
* <p>继承自原版StringDeserializer特殊定制的字符串反序列化器</p>
* <p>测试时偶然发现的图书馆搜索api返回的json中`pub_year``abstract`等一些本应该是字符串值的字段有概率会出现为空数组的奇葩情况...</p>
* <p>想了半天也没想明白那系统究竟是怎么在字符串里蹦出`[]`...</p>
*/
class SpecialStringDeserializer extends StringDeserializer {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
// The critical path: ensure we handle the common case first.
if (p.hasToken(JsonToken.VALUE_STRING)) {
return p.getText();
}
// [databind#381]
if (p.hasToken(JsonToken.START_ARRAY)) {
// 仅修改了这行
return p.getValueAsString("");
}
return _parseString(p, ctxt, this);
}
}

@ -0,0 +1,59 @@
package cn.wustlinghang.mywust.core.request.service.library;
import cn.wustlinghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.*;
public class BookCoverImageUrlApiService extends BaseLibraryApiService {
public BookCoverImageUrlApiService(Requester requester) {
super(requester);
}
public List<String> getBookCoverImageUrl(String isbn) throws ApiException, IOException {
HttpRequest request = LibraryRequestFactory.bookCoverImageUrlRequest(isbn);
HttpResponse response = requester.get(request);
checkResponse(response);
// 因为只查了一本书,所以path(isbn)直接一步到位就行了
JsonNode imageResultJson = objectMapper.readTree(response.getBody()).path("data").path(isbn);
List<String> covers = new ArrayList<>(imageResultJson.size());
for (JsonNode resultItemJson : imageResultJson) {
covers.add(resultItemJson.path("imageUrl").asText()
.replaceAll("^//", "http://")
);
}
return covers;
}
public Map<String, List<String>> getBookCoverImageUrl(List<String> isbnList) throws ApiException, IOException {
HttpRequest request = LibraryRequestFactory.bookCoverImageUrlRequest(isbnList);
HttpResponse response = requester.get(request);
checkResponse(response);
JsonNode data = objectMapper.readTree(response.getBody()).path("data");
Map<String, List<String>> result = new HashMap<>(data.size());
// 遍历data下每本书
Iterator<Map.Entry<String, JsonNode>> it = data.fields();
while (it.hasNext()) {
Map.Entry<String, JsonNode> bookItemJson = it.next();
List<String> covers = new ArrayList<>(bookItemJson.getValue().size());
for (JsonNode resultItemJson : bookItemJson.getValue()) {
covers.add(resultItemJson.path("imageUrl").asText()
.replaceAll("^//", "http://")
);
}
result.put(bookItemJson.getKey(), covers);
}
return result;
}
}

@ -0,0 +1,70 @@
package cn.wustlinghang.mywust.core.request.service.library;
import cn.wustlinghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.wustlinghang.mywust.data.library.parsed.BookDetail;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import cn.wustlinghang.mywust.util.StringUtil;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class BookDetailApiService extends BaseLibraryApiService {
public BookDetailApiService(Requester requester) {
super(requester);
}
public BookDetail getBookDetail(String bookId) throws ApiException, IOException {
HttpRequest infoRequest = LibraryRequestFactory.bookInfoRequest(bookId);
HttpResponse infoResponse = requester.get(infoRequest);
checkResponse(infoResponse);
JsonNode data = objectMapper.readTree(infoResponse.getBody())
.path("data").path("map");
JsonNode baseInfo = data.path("baseInfo").path("map");
JsonNode detailInfo = data.path("detailInfo").path("map");
Map<String, String> extraInfoMap = new HashMap<>(detailInfo.size());
Iterator<Map.Entry<String, JsonNode>> it = detailInfo.fields();
while (it.hasNext()) {
Map.Entry<String, JsonNode> field = it.next();
extraInfoMap.put(field.getKey(), StringUtil.cleanHtml(field.getValue().asText("无")));
}
String isbn = baseInfo.get("isbn").asText("无");
String author = baseInfo.path("author").asText("无");
String title = baseInfo.path("title").asText("无");
HttpRequest doubanInfoRequest = LibraryRequestFactory.bookDoubanInfoRequest(isbn);
HttpResponse doubanInfoResponse = requester.get(doubanInfoRequest);
checkResponse(doubanInfoResponse);
JsonNode doubanInfo = objectMapper.readTree(doubanInfoResponse.getBody()).path("data");
String authorDescribe = doubanInfo.path("authorInfo").asText("无");
String catalog = doubanInfo.path("catalog").asText("无");
String summary = doubanInfo.path("content").asText("无");
String introduction = doubanInfo.path("intro").asText(summary);
String coverUrl = doubanInfo.path("imageUrl").asText("")
.replaceAll("^//", "http://");
return BookDetail.builder()
.isbn(isbn)
.author(author)
.title(title)
.extraInfoMap(extraInfoMap)
.authorDescribe(StringUtil.cleanHtml(authorDescribe))
.catalog(StringUtil.cleanHtml(catalog))
.summary(StringUtil.cleanHtml(summary))
.introduction(StringUtil.cleanHtml(introduction))
.coverUrl(coverUrl)
.build();
}
}

@ -0,0 +1,39 @@
package cn.wustlinghang.mywust.core.request.service.library;
import cn.wustlinghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.wustlinghang.mywust.data.library.parsed.BookHolding;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.List;
public class BookHoldingApiService extends BaseLibraryApiService {
public BookHoldingApiService(Requester requester) {
super(requester);
}
public List<BookHolding> getHoldingList(String id)
throws ApiException, IOException, ParseException {
HttpRequest loanRequest = LibraryRequestFactory.bookHoldingRequest(id);
HttpResponse loanResponse = requester.get(loanRequest);
checkResponse(loanResponse);
try {
JsonNode data = objectMapper.readTree(loanResponse.getBody()).path("data");
// 这里的holding是个string值,需要独立解析(坑人)
JsonNode holdings = data.path("holdings");
return objectMapper.readValue(holdings.asText("[]"), bookHoldingListType);
} catch (JacksonException e) {
throw new ParseException(e.getMessage(), "");
}
}
}

@ -0,0 +1,52 @@
package cn.wustlinghang.mywust.core.request.service.library;
import cn.wustlinghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.wustlinghang.mywust.data.library.PagingResult;
import cn.wustlinghang.mywust.data.library.origin.CurrentLoanBook;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.List;
public class CurrentLoanApiService extends BaseLibraryApiService {
public CurrentLoanApiService(Requester requester) {
super(requester);
}
public PagingResult<List<CurrentLoanBook>> getCurrentLoan(String cookie, int page, int pageSize)
throws ApiException, IOException, ParseException {
HttpRequest loanRequest = LibraryRequestFactory.currentLoanRequest(cookie, page, pageSize);
HttpResponse loanResponse = requester.get(loanRequest);
checkResponse(loanResponse);
try {
JsonNode data = objectMapper.readTree(loanResponse.getBody()).path("data");
// 获取,计算分页数据
pageSize = data.path("pageSize").asInt(pageSize);
int currentPage = data.path("currentPage").asInt(page);
int totalResult = data.path("total").asInt(0);
int totalPage = data.path("totalPage").asInt(0);
JsonNode itemsJson = data.path("items");
List<CurrentLoanBook> books = objectMapper.treeToValue(itemsJson, currentLoanBookListType);
return PagingResult.<List<CurrentLoanBook>>builder()
.currentPage(currentPage)
.totalResult(totalResult)
.pageSize(pageSize)
.totalPage(totalPage)
.data(books)
.build();
} catch (JacksonException e) {
throw new ParseException(e.getMessage(), "");
}
}
}

@ -0,0 +1,53 @@
package cn.wustlinghang.mywust.core.request.service.library;
import cn.wustlinghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.wustlinghang.mywust.data.library.PagingResult;
import cn.wustlinghang.mywust.data.library.origin.HistoryLoanBook;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.List;
public class LoanHistoryApiService extends BaseLibraryApiService {
public LoanHistoryApiService(Requester requester) {
super(requester);
}
public PagingResult<List<HistoryLoanBook>> getLoanHistory(String cookie, int page, int pageSize)
throws ApiException, IOException, ParseException {
HttpRequest request = LibraryRequestFactory.loanHistoryRequest(cookie, page, pageSize);
HttpResponse response = requester.get(request);
checkResponse(response);
try {
JsonNode data = objectMapper.readTree(response.getBody()).path("data");
// 获取,计算分页数据
pageSize = data.path("pageSize").asInt(pageSize);
int currentPage = data.path("currentPage").asInt(page);
int totalResult = data.path("total").asInt(0);
int totalPage = data.path("totalPage").asInt(0);
JsonNode itemsJson = data.path("items");
List<HistoryLoanBook> books = objectMapper.treeToValue(itemsJson, historyLoanBookListType);
return PagingResult.<List<HistoryLoanBook>>builder()
.currentPage(currentPage)
.totalResult(totalResult)
.pageSize(pageSize)
.totalPage(totalPage)
.data(books)
.build();
} catch (JacksonException e) {
throw new ParseException(e.getMessage(), "");
}
}
}

@ -0,0 +1,56 @@
package cn.wustlinghang.mywust.core.request.service.library;
import cn.wustlinghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.wustlinghang.mywust.data.library.PagingResult;
import cn.wustlinghang.mywust.data.library.origin.BaseLoanBook;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.List;
@Slf4j
public class OverdueSoonApiService extends BaseLibraryApiService {
public OverdueSoonApiService(Requester requester) {
super(requester);
}
public PagingResult<List<BaseLoanBook>> getOverdueSoon(String cookie, int page, int pageSize)
throws ApiException, IOException, ParseException {
HttpRequest request = LibraryRequestFactory.overdueSoonRequest(cookie, page, pageSize);
HttpResponse response = requester.get(request);
checkResponse(response);
try {
// todo 这里即将到期书籍字段跟当前借阅和借阅历史字段格式貌似有点不太一样(data字段是个数组)
// 但是目前手上没有样本,因此这里还需要再测试测试
JsonNode data = objectMapper.readTree(response.getBody()).path("data");
// 获取,计算分页数据
pageSize = data.path("pageSize").asInt(pageSize);
int currentPage = data.path("currentPage").asInt(page);
int totalResult = data.path("total").asInt(0);
int totalPage = data.path("totalPage").asInt(0);
JsonNode itemsJson = data.path("items");
List<BaseLoanBook> baseLoanBooks = objectMapper.treeToValue(itemsJson, loanBookListType);
return PagingResult.<List<BaseLoanBook>>builder()
.currentPage(currentPage)
.totalResult(totalResult)
.pageSize(pageSize)
.totalPage(totalPage)
.data(baseLoanBooks)
.build();
} catch (JacksonException e) {
throw new ParseException(e.getMessage(), "");
}
}
}

@ -0,0 +1,68 @@
package cn.wustlinghang.mywust.core.request.service.library;
import cn.wustlinghang.mywust.core.request.factory.library.LibraryRequestFactory;
import cn.wustlinghang.mywust.data.library.PagingResult;
import cn.wustlinghang.mywust.data.library.origin.BookSearchRequest;
import cn.wustlinghang.mywust.data.library.origin.BookSearchResult;
import cn.wustlinghang.mywust.data.library.parsed.BookHolding;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class SearchApiService extends BaseLibraryApiService {
public SearchApiService(Requester requester) {
super(requester);
}
public PagingResult<List<BookSearchResult>> search(String keyword, int page, int pageSize)
throws ApiException, IOException, ParseException {
return search(new BookSearchRequest(keyword, pageSize, page));
}
public PagingResult<List<BookSearchResult>> search(BookSearchRequest request)
throws ApiException, IOException, ParseException {
HttpRequest searchRequest = LibraryRequestFactory.bookSearchRequest(request);
HttpResponse searchResponse = requester.post(searchRequest);
checkResponse(searchResponse);
try {
JsonNode data = objectMapper.readTree(searchResponse.getBody()).path("data");
int pageSize = data.path("limit").asInt(request.getPageSize());
int currentPage = data.path("offset").asInt(request.getPage()) / pageSize + 1;
int totalResult = data.path("actualTotal").asInt(0);
int totalPage = totalResult / pageSize + 1;
JsonNode dataList = data.get("dataList");
List<BookSearchResult> books = new ArrayList<>(dataList.size());
for (JsonNode item : dataList) {
// 反序列化holding字段,原字段为字符串值,无法直接原样转换
List<BookHolding> holdings = objectMapper.readValue(
item.path("holdings").asText("[]"), bookHoldingListType);
BookSearchResult book = objectMapper.treeToValue(item, BookSearchResult.class);
book.setHoldings(holdings);
books.add(book);
}
return PagingResult.<List<BookSearchResult>>builder()
.currentPage(currentPage)
.totalResult(totalResult)
.pageSize(pageSize)
.totalPage(totalPage)
.data(books)
.build();
} catch (JacksonException e) {
e.printStackTrace();
throw new ParseException(e.getMessage(), "");
}
}
}

@ -1,8 +1,8 @@
package cn.linghang.mywust.core.request.service.physics;
package cn.wustlinghang.mywust.core.request.service.physics;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.network.Requester;
import cn.linghang.mywust.network.entitys.HttpResponse;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
public abstract class PhysicsApiServiceBase {
protected final Requester requester;

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.physics;
package cn.wustlinghang.mywust.core.request.service.physics;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.physics.PhysicsSystemRequestFactory;
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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.physics.PhysicsSystemRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
@ -15,7 +15,7 @@ public class PhysicsCourseApiService extends PhysicsApiServiceBase {
}
public String getPage(String cookie, RequestClientOption requestClientOption) throws IOException, ApiException {
requestClientOption.setFallowUrlRedirect(false);
requestClientOption.setFollowUrlRedirect(false);
// 直接请求真正的课表页
HttpRequest coursePageRequest = PhysicsSystemRequestFactory.physicsCourseRequest(cookie);

@ -1,14 +1,14 @@
package cn.linghang.mywust.core.request.service.physics;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.physics.PhysicsScoreListPageParser;
import cn.linghang.mywust.core.request.factory.physics.PhysicsSystemRequestFactory;
import cn.linghang.mywust.core.util.PageFormExtractor;
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;
package cn.wustlinghang.mywust.core.request.service.physics;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.physics.PhysicsScoreListPageParser;
import cn.wustlinghang.mywust.core.request.factory.physics.PhysicsSystemRequestFactory;
import cn.wustlinghang.mywust.core.util.PageFormExtractor;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.ArrayList;

@ -1,13 +1,13 @@
package cn.linghang.mywust.core.request.service.undergraduate;
package cn.wustlinghang.mywust.core.request.service.undergraduate;
import cn.linghang.mywust.core.api.UndergradUrls;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.RequestFactory;
import cn.linghang.mywust.core.util.BkjxUtil;
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.wustlinghang.mywust.core.api.UndergradUrls;
import cn.wustlinghang.mywust.core.util.BkjxUtil;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import cn.wustlinghang.mywust.network.request.RequestFactory;
import java.io.IOException;
import java.util.Map;
@ -21,11 +21,13 @@ public abstract class UndergradApiServiceBase {
public void checkResponse(HttpResponse response) throws ApiException {
// 检查响应是否正确
if (response.getBody() == null ||
boolean cookieInvalid = response.getBody() == null ||
response.getStatusCode() != HttpResponse.HTTP_OK ||
BkjxUtil.hasLoginFinger(response.getBody())) {
BkjxUtil.needLogin(response.getBody());
if (cookieInvalid) {
throw new ApiException(ApiException.Code.COOKIE_INVALID);
} else if (BkjxUtil.isBannedResponse(response)) {
throw new ApiException(ApiException.Code.UNDERGRAD_BANNED_IN_EXCLUSIVE_TIME);
}
}
@ -41,5 +43,6 @@ public abstract class UndergradApiServiceBase {
}
public abstract String getPage(String cookie, Map<String, String> params, RequestClientOption option) throws ApiException, IOException;
public abstract String getPage(String cookie, Map<String, String> params) throws ApiException, IOException;
}

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.undergraduate;
package cn.wustlinghang.mywust.core.request.service.undergraduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Map;
@ -40,7 +40,7 @@ public class UndergradCourseTableApiService extends UndergradApiServiceBase {
super.checkResponse(response);
return new String(response.getBody());
return response.getStringBody();
}
public String getPage(String term, String cookies) throws IOException, ApiException {

@ -1,13 +1,13 @@
package cn.linghang.mywust.core.request.service.undergraduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.exception.ParseException;
import cn.linghang.mywust.core.parser.undergraduate.UndergradCreditStatusIndexParser;
import cn.linghang.mywust.core.request.factory.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;
package cn.wustlinghang.mywust.core.request.service.undergraduate;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.exception.ParseException;
import cn.wustlinghang.mywust.core.parser.undergraduate.UndergradCreditStatusIndexParser;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Map;

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.undergraduate;
package cn.wustlinghang.mywust.core.request.service.undergraduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.undergraduate;
package cn.wustlinghang.mywust.core.request.service.undergraduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Map;
@ -32,7 +32,7 @@ public class UndergradScoreApiService extends UndergradApiServiceBase {
super.checkResponse(response);
return new String(response.getBody());
return response.getStringBody();
}
public String getPage(String cookies) throws IOException, ApiException {

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.undergraduate;
package cn.wustlinghang.mywust.core.request.service.undergraduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Map;
@ -32,7 +32,7 @@ public class UndergradStudentInfoApiService extends UndergradApiServiceBase {
super.checkResponse(response);
return new String(response.getBody());
return response.getStringBody();
}
public String getPage(String cookies) throws IOException, ApiException {

@ -1,11 +1,11 @@
package cn.linghang.mywust.core.request.service.undergraduate;
package cn.wustlinghang.mywust.core.request.service.undergraduate;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.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.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Map;
@ -32,7 +32,7 @@ public class UndergradTrainingPlanApiService extends UndergradApiServiceBase {
super.checkResponse(response);
return new String(response.getBody());
return response.getStringBody();
}
public String getPage(String cookies) throws IOException, ApiException {

@ -1,12 +1,12 @@
package cn.linghang.mywust.core.request.service.undergraduate.global;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.undergrade.global.BkjxAllCourseRequestFactory;
import cn.linghang.mywust.core.request.service.undergraduate.UndergradApiServiceBase;
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;
package cn.wustlinghang.mywust.core.request.service.undergraduate.global;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.global.BkjxAllCourseRequestFactory;
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradApiServiceBase;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Map;

@ -1,15 +1,15 @@
package cn.linghang.mywust.core.request.service.undergraduate.global;
import cn.linghang.mywust.core.api.ConstantParams;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.linghang.mywust.core.request.service.undergraduate.UndergradApiServiceBase;
import cn.linghang.mywust.data.global.Building;
import cn.linghang.mywust.data.global.Campus;
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;
package cn.wustlinghang.mywust.core.request.service.undergraduate.global;
import cn.wustlinghang.mywust.core.api.ConstantParams;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.BkjxRequestFactory;
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradApiServiceBase;
import cn.wustlinghang.mywust.data.global.Building;
import cn.wustlinghang.mywust.data.global.Campus;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@ -1,12 +1,12 @@
package cn.linghang.mywust.core.request.service.undergraduate.global;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.undergrade.global.BkjxAllCourseRequestFactory;
import cn.linghang.mywust.core.request.service.undergraduate.UndergradApiServiceBase;
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;
package cn.wustlinghang.mywust.core.request.service.undergraduate.global;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.global.BkjxAllCourseRequestFactory;
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradApiServiceBase;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Map;

@ -1,12 +1,12 @@
package cn.linghang.mywust.core.request.service.undergraduate.global;
import cn.linghang.mywust.exception.ApiException;
import cn.linghang.mywust.core.request.factory.undergrade.global.BkjxAllCourseRequestFactory;
import cn.linghang.mywust.core.request.service.undergraduate.UndergradApiServiceBase;
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;
package cn.wustlinghang.mywust.core.request.service.undergraduate.global;
import cn.wustlinghang.mywust.exception.ApiException;
import cn.wustlinghang.mywust.core.request.factory.undergrade.global.BkjxAllCourseRequestFactory;
import cn.wustlinghang.mywust.core.request.service.undergraduate.UndergradApiServiceBase;
import cn.wustlinghang.mywust.network.RequestClientOption;
import cn.wustlinghang.mywust.network.Requester;
import cn.wustlinghang.mywust.network.entitys.HttpRequest;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.io.IOException;
import java.util.Map;

@ -0,0 +1,70 @@
package cn.wustlinghang.mywust.core.util;
import cn.wustlinghang.mywust.network.entitys.HttpResponse;
import java.nio.charset.StandardCharsets;
/**
* 专属于bkjx本科教学系统服务的工具类
*/
public class BkjxUtil {
// 在“Bkjx”系统里边如果收到的响应开头是这个的话多半是cookie无效了,需要重新登录获取cookie
private static final byte[] LOGIN_MESSAGE_RESPONSE_FINGER = "<script".getBytes(StandardCharsets.UTF_8);
/**
* <p>通过粗暴地比较响应字节前几个字符是否为登录跳转特征字符判断是否需要重新登录</p>
* <p>只比较前若干个字节在数据较大时比较有用</p>
* <p>对于null对象一律认为不需要</p>
*
* @param response 响应的字节
* @return 是否需要重新登录
*/
public static boolean needLogin(byte[] response) {
if (response == null) {
return false;
}
for (int i = 0; i < LOGIN_MESSAGE_RESPONSE_FINGER.length; i++) {
if (LOGIN_MESSAGE_RESPONSE_FINGER[i] != response[i]) {
return false;
}
}
return true;
}
/**
* <p>检查是否为专属选课时间封号</p>
* <p>对于null对象一律认为不是</p>
*
* @param response HttpResponse响应
* @return 是否为封号响应
*/
public static boolean isBannedResponse(HttpResponse response) {
if (response == null || response.getBody() == null) {
return false;
}
// 这里用了个取巧的办法,如果响应体大于400bytes,则直接认为不是封号的响应,不继续比较关键字
if (response.getBody().length > 400) {
return false;
}
return isBannedResponse(response.getStringBody());
}
/**
* <p>检查是否为专属选课时间封号</p>
* <p>对于null对象一律认为不是</p>
*
* @param responseText 响应字符串
* @return 是否为封号响应
*/
public static boolean isBannedResponse(String responseText) {
if (responseText == null) {
return false;
}
return responseText.contains("当前登录帐号已被禁用");
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save