pull/5/head
fengyuecanzhu 4 years ago
parent 306e30ae70
commit dae4748674
  1. 4
      .idea/assetWizardSettings.xml
  2. 6
      app/src/main/assets/updatelog.fy
  3. 3
      app/src/main/java/xyz/fycz/myreader/application/App.java
  4. 149
      app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java
  5. 1
      app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java
  6. 50
      app/src/main/java/xyz/fycz/myreader/base/BitIntentDataManager.java
  7. 1
      app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
  8. 4
      app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntityUtil.kt
  9. 6
      app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ThirdSourceUtil.java
  10. 64
      app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java
  11. 14
      app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/FindRule.java
  12. 25
      app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/InfoRule.java
  13. 16
      app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BookSourceManager.java
  14. 33
      app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByRegex.java
  15. 101
      app/src/main/java/xyz/fycz/myreader/model/third2/content/BookInfo.java
  16. 168
      app/src/main/java/xyz/fycz/myreader/model/third2/content/BookList.java
  17. 51
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
  18. 3
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java
  19. 12
      app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
  20. 3
      app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java
  21. 1
      app/src/main/java/xyz/fycz/myreader/ui/activity/SourceDebugActivity.java
  22. 18
      app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java
  23. 4
      app/src/main/java/xyz/fycz/myreader/util/help/JsExtensions.java
  24. 6
      app/src/main/java/xyz/fycz/myreader/util/utils/AdUtils.java
  25. 2
      app/src/main/java/xyz/fycz/myreader/util/utils/MD5Utils.kt
  26. 2
      app/src/main/java/xyz/fycz/myreader/webapi/BookApi.java
  27. 31
      app/src/main/java/xyz/fycz/myreader/webapi/ThirdSourceApi.java
  28. 7
      app/src/main/res/drawable/ic_source.xml
  29. 6
      app/src/main/res/layout/fragment_mine.xml
  30. 5
      app/src/main/res/menu/menu_book_detail.xml
  31. 6
      app/src/main/res/menu/menu_read.xml
  32. 3
      app/src/main/res/values/strings.xml
  33. 4
      app/version_code.properties

@ -14,8 +14,8 @@
<option name="values"> <option name="values">
<map> <map>
<entry key="assetSourceType" value="FILE" /> <entry key="assetSourceType" value="FILE" />
<entry key="outputName" value="ic_edit" /> <entry key="outputName" value="ic_source" />
<entry key="sourceFile" value="F:\SVG图标\编辑.svg" /> <entry key="sourceFile" value="F:\SVG图标\代码.svg" />
</map> </map>
</option> </option>
</PersistentState> </PersistentState>

@ -1,9 +1,15 @@
2021.05.15
风月读书v1.9.8-beta
更新内容:
1、修复搜索闪退的bug
2021.05.15 2021.05.15
风月读书v1.9.7-beta 风月读书v1.9.7-beta
更新内容: 更新内容:
1、优化书源结构 1、优化书源结构
2、书源带cookie请求 2、书源带cookie请求
3、第三方书源优化,修复bug 3、第三方书源优化,修复bug
4、书源支持登录
2021.05.14 2021.05.14
风月读书v1.9.6-beta 风月读书v1.9.6-beta

@ -76,6 +76,7 @@ public class App extends Application {
super.onCreate(); super.onCreate();
application = this; application = this;
debug = isApkInDebug(this); debug = isApkInDebug(this);
CrashHandler.register(this);
firstInit(); firstInit();
SSLSocketClient.trustAllHosts();//信任所有证书 SSLSocketClient.trustAllHosts();//信任所有证书
RxJavaPlugins.setErrorHandler(Functions.emptyConsumer()); RxJavaPlugins.setErrorHandler(Functions.emptyConsumer());
@ -283,7 +284,7 @@ public class App extends Application {
App.getApplication().newThread(() -> { App.getApplication().newThread(() -> {
try { try {
String url = "https://shimo.im/docs/cqkgjPRRydYYhQKt/read"; String url = "https://shimo.im/docs/cqkgjPRRydYYhQKt/read";
if (getApplication().debug) { if (debug) {
url = "https://shimo.im/docs/zfzpda7MUGskOC9v/read"; url = "https://shimo.im/docs/zfzpda7MUGskOC9v/read";
} }
String html = OkHttpUtils.getHtml(url); String html = OkHttpUtils.getHtml(url);

@ -0,0 +1,149 @@
package xyz.fycz.myreader.application;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import androidx.annotation.NonNull;
import org.jetbrains.annotations.NotNull;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.ui.activity.SplashActivity;
import xyz.fycz.myreader.util.utils.FileUtils;
/**
* @author fengyue
* @date 2021/5/16 11:01
*/
public final class CrashHandler implements Thread.UncaughtExceptionHandler {
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
/**
* 注册 Crash 监听
*/
public static void register(Application application) {
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(application));
}
private final Application mApplication;
private final Thread.UncaughtExceptionHandler mNextHandler;
private CrashHandler(Application application) {
mApplication = application;
mNextHandler = Thread.getDefaultUncaughtExceptionHandler();
if (getClass().getName().equals(mNextHandler.getClass().getName())) {
// 请不要重复注册 Crash 监听
throw new IllegalStateException("are you ok?");
}
}
@SuppressLint("ApplySharedPref")
@Override
public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
saveCrashLog(throwable);
// 不去触发系统的崩溃处理(com.android.internal.os.RuntimeInit$KillApplicationHandler)
if (mNextHandler != null && !mNextHandler.getClass().getName().startsWith("com.android.internal.os")) {
mNextHandler.uncaughtException(thread, throwable);
}
// 杀死进程(这个事应该是系统干的,但是它会多弹出一个崩溃对话框,所以需要我们自己手动杀死进程)
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
}
private void saveCrashLog(Throwable throwable) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
throwable.printStackTrace(printWriter);
Throwable cause = throwable.getCause();
if (cause != null) {
cause.printStackTrace(printWriter);
}
String mStackTrace = stringWriter.toString();
Resources res = mApplication.getResources();
DisplayMetrics displayMetrics = res.getDisplayMetrics();
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
String targetResource;
if (displayMetrics.densityDpi > 480) {
targetResource = "xxxhdpi";
} else if (displayMetrics.densityDpi > 320) {
targetResource = "xxhdpi";
} else if (displayMetrics.densityDpi > 240) {
targetResource = "xhdpi";
} else if (displayMetrics.densityDpi > 160) {
targetResource = "hdpi";
} else if (displayMetrics.densityDpi > 120) {
targetResource = "mdpi";
} else {
targetResource = "ldpi";
}
StringBuilder builder = new StringBuilder();
builder.append("设备品牌:\t").append(Build.BRAND)
.append("\n设备型号:\t").append(Build.MODEL)
.append("\n设备类型:\t").append(isTablet() ? "平板" : "手机");
builder.append("\n屏幕宽高:\t").append(screenWidth).append(" x ").append(screenHeight)
.append("\n屏幕密度:\t").append(displayMetrics.densityDpi)
.append("\n目标资源:\t").append(targetResource);
builder.append("\n安卓版本:\t").append(Build.VERSION.RELEASE)
.append("\nAPI 版本:\t").append(Build.VERSION.SDK_INT)
.append("\nCPU 架构:\t").append(Build.SUPPORTED_ABIS[0]);
builder.append("\n应用版本:\t").append(App.getStrVersionName())
.append("\n版本代码:\t").append(App.getVersionCode());
try {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm", Locale.getDefault());
PackageInfo packageInfo = mApplication.getPackageManager().getPackageInfo(mApplication.getPackageName(), PackageManager.GET_PERMISSIONS);
builder.append("\n首次安装:\t").append(dateFormat.format(new Date(packageInfo.firstInstallTime)))
.append("\n最近安装:\t").append(dateFormat.format(new Date(packageInfo.lastUpdateTime)))
.append("\n崩溃时间:\t").append(dateFormat.format(new Date()));
} catch (PackageManager.NameNotFoundException ignored) {
}
String mPhoneInfo = builder.toString();
long timestamp = System.currentTimeMillis();
String time = formatter.format(new Date());
String fileName = "crash-" + time + "-" + timestamp + ".log";
String path = APPCONST.LOG_DIR + fileName;
FileUtils.writeText(mPhoneInfo + "\n\n" + mStackTrace, FileUtils.getFile(path));
}
/**
* 判断当前设备是否是平板
*/
public boolean isTablet() {
return (mApplication.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
}

@ -23,6 +23,7 @@ import me.imid.swipebacklayout.lib.app.SwipeBackActivity;
import xyz.fycz.myreader.ActivityManage; import xyz.fycz.myreader.ActivityManage;
import xyz.fycz.myreader.R; import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App; import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.application.CrashHandler;
import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.util.StatusBarUtil; import xyz.fycz.myreader.util.StatusBarUtil;

@ -0,0 +1,50 @@
package xyz.fycz.myreader.base;
import android.content.Intent;
import java.util.HashMap;
import java.util.Map;
import xyz.fycz.myreader.common.APPCONST;
public class BitIntentDataManager {
private static Map<String, Object> bigData;
private static BitIntentDataManager instance = null;
private BitIntentDataManager() {
bigData = new HashMap<>();
}
public static BitIntentDataManager getInstance() {
if (instance == null) {
synchronized (BitIntentDataManager.class) {
if (instance == null) {
instance = new BitIntentDataManager();
}
}
}
return instance;
}
public Object getData(String key) {
Object object = bigData.get(key);
bigData.remove(key);
return object;
}
public Object getData(Intent intent){
String dataKey = intent.getStringExtra(APPCONST.DATA_KEY);
return getData(dataKey);
}
public void putData(String key, Object data) {
bigData.put(key, data);
}
public void putData(Intent intent, Object data){
String dataKey = String.valueOf(System.currentTimeMillis());
intent.putExtra(APPCONST.DATA_KEY, dataKey);
putData(dataKey, data);
}
}

@ -46,6 +46,7 @@ public class APPCONST {
public static final String JSON_PATH = "JsonPath"; public static final String JSON_PATH = "JsonPath";
public static final String THIRD_SOURCE = "ThirdSource"; public static final String THIRD_SOURCE = "ThirdSource";
public static final String DATA_KEY = "data_key";
public static final String BOOK = "book"; public static final String BOOK = "book";
public static final String TITLE = "title"; public static final String TITLE = "title";
public static final String FIND_CRAWLER = "findCrawler"; public static final String FIND_CRAWLER = "findCrawler";

@ -52,6 +52,8 @@ object EditEntityUtil {
fun getInfoEntities(infoRule: InfoRule? = InfoRule()): List<EditEntity> { fun getInfoEntities(infoRule: InfoRule? = InfoRule()): List<EditEntity> {
val infoEntities: ArrayList<EditEntity> = ArrayList() val infoEntities: ArrayList<EditEntity> = ArrayList()
infoEntities.apply { infoEntities.apply {
add(EditEntity("urlPattern", infoRule?.urlPattern, R.string.book_url_pattern, ""))
add(EditEntity("init", infoRule?.init, R.string.rule_book_info_init))
add(EditEntity("name", infoRule?.name, R.string.r_book_name)) add(EditEntity("name", infoRule?.name, R.string.r_book_name))
add(EditEntity("author", infoRule?.author, R.string.r_author)) add(EditEntity("author", infoRule?.author, R.string.r_author))
add(EditEntity("type", infoRule?.type, R.string.rule_book_type)) add(EditEntity("type", infoRule?.type, R.string.rule_book_type))
@ -142,6 +144,8 @@ object EditEntityUtil {
val infoRule = InfoRule() val infoRule = InfoRule()
infoRuleEntities.forEach { infoRuleEntities.forEach {
when (it.key) { when (it.key) {
"urlPattern" -> infoRule.urlPattern = it.value
"init" -> infoRule.init = it.value
"name" -> infoRule.name = it.value "name" -> infoRule.name = it.value
"author" -> infoRule.author = it.value "author" -> infoRule.author = it.value
"type" -> infoRule.type = it.value "type" -> infoRule.type = it.value

@ -37,11 +37,13 @@ public class ThirdSourceUtil {
searchRule.setDesc(bean.getRuleSearchIntroduce()); searchRule.setDesc(bean.getRuleSearchIntroduce());
searchRule.setLastChapter(bean.getRuleSearchLastChapter()); searchRule.setLastChapter(bean.getRuleSearchLastChapter());
searchRule.setImgUrl(bean.getRuleSearchCoverUrl()); searchRule.setImgUrl(bean.getRuleSearchCoverUrl());
searchRule.setTocUrl(bean.getRuleSearchNoteUrl()); searchRule.setInfoUrl(bean.getRuleSearchNoteUrl());
searchRule.setRelatedWithInfo(true); searchRule.setRelatedWithInfo(true);
bookSource.setSearchRule(searchRule); bookSource.setSearchRule(searchRule);
InfoRule infoRule = new InfoRule(); InfoRule infoRule = new InfoRule();
infoRule.setUrlPattern(bean.getRuleBookUrlPattern());
infoRule.setInit(bean.getRuleBookInfoInit());
infoRule.setName(bean.getRuleBookName()); infoRule.setName(bean.getRuleBookName());
infoRule.setAuthor(bean.getRuleBookAuthor()); infoRule.setAuthor(bean.getRuleBookAuthor());
infoRule.setType(bean.getRuleBookKind()); infoRule.setType(bean.getRuleBookKind());
@ -72,7 +74,7 @@ public class ThirdSourceUtil {
findRule.setDesc(bean.getRuleFindIntroduce()); findRule.setDesc(bean.getRuleFindIntroduce());
findRule.setLastChapter(bean.getRuleFindLastChapter()); findRule.setLastChapter(bean.getRuleFindLastChapter());
findRule.setImgUrl(bean.getRuleFindCoverUrl()); findRule.setImgUrl(bean.getRuleFindCoverUrl());
findRule.setTocUrl(bean.getRuleFindNoteUrl()); findRule.setInfoUrl(bean.getRuleFindNoteUrl());
bookSource.setFindRule(findRule); bookSource.setFindRule(findRule);
return bookSource; return bookSource;
} }

@ -11,6 +11,7 @@ import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated; import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id; import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Transient; import org.greenrobot.greendao.annotation.Transient;
import xyz.fycz.myreader.greendao.service.BookService; import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.StringHelper; import xyz.fycz.myreader.util.StringHelper;
@ -76,17 +77,20 @@ public class Book implements Serializable {
@Transient @Transient
private Map<String, String> variableMap; private Map<String, String> variableMap;
@Transient
private Map<String, String> catheMap;
@Generated(hash = 1839243756) @Generated(hash = 1839243756)
public Book() { public Book() {
} }
@Generated(hash = 1910282685) @Generated(hash = 1910282685)
public Book(String id, String name, String chapterUrl, String infoUrl, String imgUrl, String desc, public Book(String id, String name, String chapterUrl, String infoUrl, String imgUrl, String desc,
String author, String type, String updateDate, String wordCount, String status, String author, String type, String updateDate, String wordCount, String status,
String newestChapterId, String newestChapterTitle, String historyChapterId, int histtoryChapterNum, String newestChapterId, String newestChapterTitle, String historyChapterId, int histtoryChapterNum,
int sortCode, int noReadNum, int chapterTotalNum, int lastReadPosition, String source, int sortCode, int noReadNum, int chapterTotalNum, int lastReadPosition, String source,
boolean isCloseUpdate, boolean isDownLoadAll, String groupId, int groupSort, String tag, boolean isCloseUpdate, boolean isDownLoadAll, String groupId, int groupSort, String tag,
Boolean replaceEnable, long lastReadTime, String variable) { Boolean replaceEnable, long lastReadTime, String variable) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.chapterUrl = chapterUrl; this.chapterUrl = chapterUrl;
@ -131,96 +135,127 @@ public class Book implements Serializable {
public String getId() { public String getId() {
return this.id; return this.id;
} }
public void setId(String id) { public void setId(String id) {
this.id = id; this.id = id;
} }
public String getName() { public String getName() {
return this.name; return this.name;
} }
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
public String getChapterUrl() { public String getChapterUrl() {
return this.chapterUrl; return this.chapterUrl;
} }
public void setChapterUrl(String chapterUrl) { public void setChapterUrl(String chapterUrl) {
this.chapterUrl = chapterUrl; this.chapterUrl = chapterUrl;
} }
public String getImgUrl() { public String getImgUrl() {
return this.imgUrl; return this.imgUrl;
} }
public void setImgUrl(String imgUrl) { public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl; this.imgUrl = imgUrl;
} }
public String getDesc() { public String getDesc() {
return this.desc; return this.desc;
} }
public void setDesc(String desc) { public void setDesc(String desc) {
this.desc = desc; this.desc = desc;
} }
public String getAuthor() { public String getAuthor() {
return this.author; return this.author;
} }
public void setAuthor(String author) { public void setAuthor(String author) {
this.author = BookService.formatAuthor(author); this.author = BookService.formatAuthor(author);
} }
public String getType() { public String getType() {
return this.type; return this.type;
} }
public void setType(String type) { public void setType(String type) {
this.type = type; this.type = type;
} }
public String getUpdateDate() { public String getUpdateDate() {
return this.updateDate; return this.updateDate;
} }
public void setUpdateDate(String updateDate) { public void setUpdateDate(String updateDate) {
this.updateDate = updateDate; this.updateDate = updateDate;
} }
public String getNewestChapterId() { public String getNewestChapterId() {
return this.newestChapterId; return this.newestChapterId;
} }
public void setNewestChapterId(String newestChapterId) { public void setNewestChapterId(String newestChapterId) {
this.newestChapterId = newestChapterId; this.newestChapterId = newestChapterId;
} }
public String getNewestChapterTitle() { public String getNewestChapterTitle() {
return this.newestChapterTitle; return this.newestChapterTitle;
} }
public void setNewestChapterTitle(String newestChapterTitle) { public void setNewestChapterTitle(String newestChapterTitle) {
this.newestChapterTitle = newestChapterTitle; this.newestChapterTitle = newestChapterTitle;
} }
public String getHistoryChapterId() { public String getHistoryChapterId() {
return this.historyChapterId; return this.historyChapterId;
} }
public void setHistoryChapterId(String historyChapterId) { public void setHistoryChapterId(String historyChapterId) {
this.historyChapterId = historyChapterId; this.historyChapterId = historyChapterId;
} }
public int getHisttoryChapterNum() { public int getHisttoryChapterNum() {
return this.histtoryChapterNum; return this.histtoryChapterNum;
} }
public void setHisttoryChapterNum(int histtoryChapterNum) { public void setHisttoryChapterNum(int histtoryChapterNum) {
this.histtoryChapterNum = histtoryChapterNum; this.histtoryChapterNum = histtoryChapterNum;
} }
public int getSortCode() { public int getSortCode() {
return this.sortCode; return this.sortCode;
} }
public void setSortCode(int sortCode) { public void setSortCode(int sortCode) {
this.sortCode = sortCode; this.sortCode = sortCode;
} }
public int getNoReadNum() { public int getNoReadNum() {
return this.noReadNum; return this.noReadNum;
} }
public void setNoReadNum(int noReadNum) { public void setNoReadNum(int noReadNum) {
this.noReadNum = noReadNum; this.noReadNum = noReadNum;
} }
public int getChapterTotalNum() { public int getChapterTotalNum() {
return this.chapterTotalNum; return this.chapterTotalNum;
} }
public void setChapterTotalNum(int chapterTotalNum) { public void setChapterTotalNum(int chapterTotalNum) {
this.chapterTotalNum = chapterTotalNum; this.chapterTotalNum = chapterTotalNum;
} }
public int getLastReadPosition() { public int getLastReadPosition() {
return this.lastReadPosition; return this.lastReadPosition;
} }
public void setLastReadPosition(int lastReadPosition) { public void setLastReadPosition(int lastReadPosition) {
this.lastReadPosition = lastReadPosition; this.lastReadPosition = lastReadPosition;
} }
@ -249,6 +284,7 @@ public class Book implements Serializable {
public void setIsDownLoadAll(boolean isDownLoadAll) { public void setIsDownLoadAll(boolean isDownLoadAll) {
this.isDownLoadAll = isDownLoadAll; this.isDownLoadAll = isDownLoadAll;
} }
public String getGroupId() { public String getGroupId() {
return this.groupId; return this.groupId;
} }
@ -283,9 +319,6 @@ public class Book implements Serializable {
} }
public String getInfoUrl() { public String getInfoUrl() {
if (StringHelper.isEmpty(infoUrl)){
return chapterUrl;
}
return this.infoUrl; return this.infoUrl;
} }
@ -342,6 +375,7 @@ public class Book implements Serializable {
public void setStatus(String status) { public void setStatus(String status) {
this.status = status; this.status = status;
} }
public void putVariable(String key, String value) { public void putVariable(String key, String value) {
if (variableMap == null) { if (variableMap == null) {
variableMap = new HashMap<>(); variableMap = new HashMap<>();
@ -366,4 +400,18 @@ public class Book implements Serializable {
public void setVariable(String variable) { public void setVariable(String variable) {
this.variable = variable; this.variable = variable;
} }
public void putCathe(String key, String value) {
if (catheMap == null) {
catheMap = new HashMap<>();
}
catheMap.put(key, value);
}
public String getCathe(String key){
if (catheMap == null){
return "";
}
return catheMap.get(key);
}
} }

@ -26,6 +26,7 @@ public class FindRule implements Parcelable {
private String updateTime; private String updateTime;
private String imgUrl; private String imgUrl;
private String tocUrl; private String tocUrl;
private String infoUrl;
public FindRule() { public FindRule() {
} }
@ -43,6 +44,7 @@ public class FindRule implements Parcelable {
updateTime = in.readString(); updateTime = in.readString();
imgUrl = in.readString(); imgUrl = in.readString();
tocUrl = in.readString(); tocUrl = in.readString();
infoUrl = in.readString();
} }
@Override @Override
@ -59,6 +61,7 @@ public class FindRule implements Parcelable {
dest.writeString(updateTime); dest.writeString(updateTime);
dest.writeString(imgUrl); dest.writeString(imgUrl);
dest.writeString(tocUrl); dest.writeString(tocUrl);
dest.writeString(infoUrl);
} }
@Override @Override
@ -174,6 +177,14 @@ public class FindRule implements Parcelable {
this.tocUrl = tocUrl; this.tocUrl = tocUrl;
} }
public String getInfoUrl() {
return infoUrl;
}
public void setInfoUrl(String infoUrl) {
this.infoUrl = infoUrl;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
@ -191,7 +202,8 @@ public class FindRule implements Parcelable {
stringEquals(lastChapter, findRule.lastChapter) && stringEquals(lastChapter, findRule.lastChapter) &&
stringEquals(updateTime, findRule.updateTime) && stringEquals(updateTime, findRule.updateTime) &&
stringEquals(imgUrl, findRule.imgUrl) && stringEquals(imgUrl, findRule.imgUrl) &&
stringEquals(tocUrl, findRule.tocUrl); stringEquals(tocUrl, findRule.tocUrl) &&
stringEquals(infoUrl, findRule.infoUrl);
} }
} }

@ -16,6 +16,8 @@ import static xyz.fycz.myreader.util.utils.StringUtils.stringEquals;
* @date 2021/2/8 17:53 * @date 2021/2/8 17:53
*/ */
public class InfoRule implements Parcelable { public class InfoRule implements Parcelable {
private String urlPattern;
private String init;
private String name; private String name;
private String author; private String author;
private String type; private String type;
@ -31,6 +33,8 @@ public class InfoRule implements Parcelable {
} }
protected InfoRule(Parcel in) { protected InfoRule(Parcel in) {
urlPattern = in.readString();
init = in.readString();
name = in.readString(); name = in.readString();
author = in.readString(); author = in.readString();
type = in.readString(); type = in.readString();
@ -45,6 +49,8 @@ public class InfoRule implements Parcelable {
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(urlPattern);
dest.writeString(init);
dest.writeString(name); dest.writeString(name);
dest.writeString(author); dest.writeString(author);
dest.writeString(type); dest.writeString(type);
@ -80,7 +86,9 @@ public class InfoRule implements Parcelable {
if (o == null) o = new InfoRule(); if (o == null) o = new InfoRule();
if (getClass() != o.getClass()) return false; if (getClass() != o.getClass()) return false;
InfoRule infoRule = (InfoRule) o; InfoRule infoRule = (InfoRule) o;
return stringEquals(name, infoRule.name) && return stringEquals(urlPattern, infoRule.urlPattern) &&
stringEquals(init, infoRule.init) &&
stringEquals(name, infoRule.name) &&
stringEquals(author, infoRule.author) && stringEquals(author, infoRule.author) &&
stringEquals(type, infoRule.type) && stringEquals(type, infoRule.type) &&
stringEquals(desc, infoRule.desc) && stringEquals(desc, infoRule.desc) &&
@ -92,6 +100,21 @@ public class InfoRule implements Parcelable {
stringEquals(tocUrl, infoRule.tocUrl); stringEquals(tocUrl, infoRule.tocUrl);
} }
public String getUrlPattern() {
return urlPattern;
}
public void setUrlPattern(String urlPattern) {
this.urlPattern = urlPattern;
}
public String getInit() {
return init;
}
public void setInit(String init) {
this.init = init;
}
public String getName() { public String getName() {
return name; return name;

@ -81,11 +81,9 @@ public class BookSourceManager {
* @return * @return
*/ */
public static BookSource getBookSourceByStr(String str) { public static BookSource getBookSourceByStr(String str) {
if (NetworkUtils.isUrl(str)) { BookSource source = getBookSourceByEName(str);
return getBookSourceByUrl(str); if (source == null) source = getBookSourceByUrl(str);
} else { return source;
return getBookSourceByEName(str);
}
} }
/** /**
@ -94,7 +92,7 @@ public class BookSourceManager {
* @param url * @param url
* @return * @return
*/ */
public static BookSource getBookSourceByUrl(String url) { private static BookSource getBookSourceByUrl(String url) {
if (url == null) return getDefaultSource(); if (url == null) return getDefaultSource();
BookSource source = DbManager.getDaoSession().getBookSourceDao().load(url); BookSource source = DbManager.getDaoSession().getBookSourceDao().load(url);
if (source == null) return getDefaultSource(); if (source == null) return getDefaultSource();
@ -107,15 +105,13 @@ public class BookSourceManager {
* @param ename * @param ename
* @return * @return
*/ */
@Nullable private static BookSource getBookSourceByEName(String ename) {
public static BookSource getBookSourceByEName(String ename) { if (ename == null) return null;
if (ename == null) return getDefaultSource();
if ("local".equals(ename)) return getLocalSource(); if ("local".equals(ename)) return getLocalSource();
BookSource source = DbManager.getDaoSession().getBookSourceDao(). BookSource source = DbManager.getDaoSession().getBookSourceDao().
queryBuilder() queryBuilder()
.where(BookSourceDao.Properties.SourceEName.eq(ename)) .where(BookSourceDao.Properties.SourceEName.eq(ename))
.unique(); .unique();
if (source == null) return getDefaultSource();
return source; return source;
} }

@ -2,6 +2,7 @@ package xyz.fycz.myreader.model.third2.analyzeRule;
import android.os.Build; import android.os.Build;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -21,11 +22,16 @@ public class AnalyzeByRegex {
// 纯java模式正则表达式获取书籍详情信息 // 纯java模式正则表达式获取书籍详情信息
public static void getInfoOfRegex(String res, String[] regs, int index, public static void getInfoOfRegex(String res, String[] regs, int index,
Book book, AnalyzeRule analyzer, BookSource source, String baseUrl, String tag) throws Exception { Book book, AnalyzeRule analyzer, BookSource source, String tag) throws Exception {
Matcher resM = Pattern.compile(regs[index]).matcher(res); Matcher resM = Pattern.compile(regs[index]).matcher(res);
String baseUrl = book.getInfoUrl();
// 判断规则是否有效,当搜索列表规则无效时跳过详情页处理 // 判断规则是否有效,当搜索列表规则无效时跳过详情页处理
if (!resM.find()) { if (!resM.find()) {
Log.d(tag, "└详情预处理失败,跳过详情页解析");
Log.d(tag, "┌获取目录网址");
book.setChapterUrl(baseUrl); book.setChapterUrl(baseUrl);
book.putCathe("ChapterListHtml", res);
Log.d(tag, "└" + baseUrl);
return; return;
} }
// 判断索引的规则是最后一个规则 // 判断索引的规则是最后一个规则
@ -78,18 +84,37 @@ public class AnalyzeByRegex {
book.setName(StringUtils.formatHtml(ruleVal.get("BookName"))); book.setName(StringUtils.formatHtml(ruleVal.get("BookName")));
if (!isEmpty(ruleVal.get("BookAuthor"))) if (!isEmpty(ruleVal.get("BookAuthor")))
book.setAuthor(StringUtils.formatHtml(ruleVal.get("BookAuthor"))); book.setAuthor(StringUtils.formatHtml(ruleVal.get("BookAuthor")));
if (!isEmpty(ruleVal.get("LastChapter"))) book.setNewestChapterTitle(ruleVal.get("LastChapter")); if (!isEmpty(ruleVal.get("LastChapter")))
book.setNewestChapterTitle(ruleVal.get("LastChapter"));
if (!isEmpty(ruleVal.get("Introduce"))) if (!isEmpty(ruleVal.get("Introduce")))
book.setDesc(StringUtils.formatHtml(ruleVal.get("Introduce"))); book.setDesc(StringUtils.formatHtml(ruleVal.get("Introduce")));
if (!isEmpty(ruleVal.get("CoverUrl"))) book.setImgUrl(ruleVal.get("CoverUrl")); if (!isEmpty(ruleVal.get("CoverUrl"))) book.setImgUrl(ruleVal.get("CoverUrl"));
if (!isEmpty(ruleVal.get("ChapterUrl"))) book.setChapterUrl(NetworkUtils.getAbsoluteURL(baseUrl, ruleVal.get("ChapterUrl"))); if (!isEmpty(ruleVal.get("ChapterUrl")))
book.setChapterUrl(NetworkUtils.getAbsoluteURL(baseUrl, ruleVal.get("ChapterUrl")));
else book.setChapterUrl(baseUrl); else book.setChapterUrl(baseUrl);
//如果目录页和详情页相同,暂存页面内容供获取目录用
if (book.getChapterUrl().equals(baseUrl)) book.putCathe("ChapterListHtml", res);
// 输出调试信息
Log.d(tag, "└详情预处理完成");
Log.d(tag, "┌获取书籍名称");
Log.d(tag, "└" + book.getName());
Log.d(tag, "┌获取作者名称");
Log.d(tag, "└" + book.getAuthor());
Log.d(tag, "┌获取最新章节");
Log.d(tag, "└" + book.getNewestChapterTitle());
Log.d(tag, "┌获取简介内容");
Log.d(tag, "└" + book.getDesc());
Log.d(tag, "┌获取封面网址");
Log.d(tag, "└" + book.getImgUrl());
Log.d(tag, "┌获取目录网址");
Log.d(tag, "└" + book.getChapterUrl());
Log.d(tag, "-详情页解析完成");
} else { } else {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
do { do {
result.append(resM.group()); result.append(resM.group());
} while (resM.find()); } while (resM.find());
getInfoOfRegex(result.toString(), regs, ++index, book, analyzer, source, baseUrl, tag); getInfoOfRegex(result.toString(), regs, ++index, book, analyzer, source, tag);
} }
} }

@ -8,6 +8,7 @@ import io.reactivex.Observable;
import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.rule.BookSource; import xyz.fycz.myreader.greendao.entity.rule.BookSource;
import xyz.fycz.myreader.greendao.entity.rule.InfoRule; import xyz.fycz.myreader.greendao.entity.rule.InfoRule;
import xyz.fycz.myreader.model.third2.analyzeRule.AnalyzeByRegex;
import xyz.fycz.myreader.model.third2.analyzeRule.AnalyzeRule; import xyz.fycz.myreader.model.third2.analyzeRule.AnalyzeRule;
import xyz.fycz.myreader.util.utils.StringUtils; import xyz.fycz.myreader.util.utils.StringUtils;
@ -27,7 +28,7 @@ public class BookInfo {
public Observable<Book> analyzeBookInfo(String s, final Book book) { public Observable<Book> analyzeBookInfo(String s, final Book book) {
return Observable.create(e -> { return Observable.create(e -> {
String baseUrl = book.getInfoUrl(); String baseUrl = book.getInfoUrl();
book.setInfoUrl(baseUrl);
InfoRule infoRule = source.getInfoRule(); InfoRule infoRule = source.getInfoRule();
if (TextUtils.isEmpty(s)) { if (TextUtils.isEmpty(s)) {
e.onError(new Throwable("书籍信息获取失败" + baseUrl)); e.onError(new Throwable("书籍信息获取失败" + baseUrl));
@ -42,43 +43,67 @@ public class BookInfo {
AnalyzeRule analyzer = new AnalyzeRule(book); AnalyzeRule analyzer = new AnalyzeRule(book);
analyzer.setContent(s, baseUrl); analyzer.setContent(s, baseUrl);
Log.d(tag, "┌获取书名"); // 获取详情页预处理规则
String bookName = StringUtils.formatHtml(analyzer.getString(infoRule.getName())); String ruleInfoInit = infoRule.getInit();
if (!isEmpty(bookName)) book.setName(bookName); boolean isRegex = false;
Log.d(tag, "└" + bookName); if (!isEmpty(ruleInfoInit)) {
// 仅使用java正则表达式提取书籍详情
Log.d(tag, "┌获取作者"); if (ruleInfoInit.startsWith(":")) {
String bookAuthor = StringUtils.formatHtml(analyzer.getString(infoRule.getAuthor())); isRegex = true;
if (!isEmpty(bookAuthor)) book.setAuthor(bookAuthor); ruleInfoInit = ruleInfoInit.substring(1);
Log.d(tag, "└" + bookAuthor); Log.d(tag, "┌详情信息预处理");
AnalyzeByRegex.getInfoOfRegex(s, ruleInfoInit.split("&&"), 0, book, analyzer, source, tag);
Log.d(tag, "┌获取分类"); } else {
String bookKind = analyzer.getString(infoRule.getType()); Object object = analyzer.getElement(ruleInfoInit);
Log.d(tag, "└" + bookKind); if (object != null) {
analyzer.setContent(object);
Log.d(tag, "┌获取最新章节"); }
String bookLastChapter = analyzer.getString(infoRule.getLastChapter()); }
if (!isEmpty(bookLastChapter)) book.setNewestChapterTitle(bookLastChapter); }
Log.d(tag, "└" + bookLastChapter); if (!isRegex) {
Log.d(tag, "┌详情信息预处理");
Log.d(tag, "┌获取简介"); Object object = analyzer.getElement(ruleInfoInit);
String bookIntroduce = analyzer.getString(infoRule.getDesc()); if (object != null) analyzer.setContent(object);
if (!isEmpty(bookIntroduce)) book.setDesc(bookIntroduce); Log.d(tag, "└详情预处理完成");
Log.d(tag, "└" + bookIntroduce);
Log.d(tag, "┌获取书名");
Log.d(tag, "┌获取封面"); String bookName = StringUtils.formatHtml(analyzer.getString(infoRule.getName()));
String bookCoverUrl = analyzer.getString(infoRule.getImgUrl(), true); if (!isEmpty(bookName)) book.setName(bookName);
if (!isEmpty(bookCoverUrl)) book.setImgUrl(bookCoverUrl); Log.d(tag, "└" + bookName);
Log.d(tag, "└" + bookCoverUrl);
Log.d(tag, "┌获取作者");
Log.d(tag, "┌获取目录网址"); String bookAuthor = StringUtils.formatHtml(analyzer.getString(infoRule.getAuthor()));
String bookCatalogUrl = analyzer.getString(infoRule.getTocUrl(), true); if (!isEmpty(bookAuthor)) book.setAuthor(bookAuthor);
if (isEmpty(bookCatalogUrl)) bookCatalogUrl = baseUrl; Log.d(tag, "└" + bookAuthor);
book.setChapterUrl(bookCatalogUrl);
//如果目录页和详情页相同,暂存页面内容供获取目录用 Log.d(tag, "┌获取分类");
//if (bookCatalogUrl.equals(baseUrl)) bookInfoBean.setChapterListHtml(s); String bookKind = analyzer.getString(infoRule.getType());
Log.d(tag, "└" + book.getChapterUrl()); Log.d(tag, "└" + bookKind);
Log.d(tag, "-详情页解析完成");
Log.d(tag, "┌获取最新章节");
String bookLastChapter = analyzer.getString(infoRule.getLastChapter());
if (!isEmpty(bookLastChapter)) book.setNewestChapterTitle(bookLastChapter);
Log.d(tag, "└" + bookLastChapter);
Log.d(tag, "┌获取简介");
String bookIntroduce = analyzer.getString(infoRule.getDesc());
if (!isEmpty(bookIntroduce)) book.setDesc(bookIntroduce);
Log.d(tag, "└" + bookIntroduce);
Log.d(tag, "┌获取封面");
String bookCoverUrl = analyzer.getString(infoRule.getImgUrl(), true);
if (!isEmpty(bookCoverUrl)) book.setImgUrl(bookCoverUrl);
Log.d(tag, "└" + bookCoverUrl);
Log.d(tag, "┌获取目录网址");
String bookCatalogUrl = analyzer.getString(infoRule.getTocUrl(), true);
if (isEmpty(bookCatalogUrl)) bookCatalogUrl = baseUrl;
book.setChapterUrl(bookCatalogUrl);
//如果目录页和详情页相同,暂存页面内容供获取目录用
if (bookCatalogUrl.equals(baseUrl)) book.putCathe("ChapterListHtml", s);
Log.d(tag, "└" + book.getChapterUrl());
Log.d(tag, "-详情页解析完成");
}
e.onNext(book); e.onNext(book);
e.onComplete(); e.onComplete();
}); });

@ -65,67 +65,76 @@ public class BookList {
AnalyzeRule analyzer = new AnalyzeRule(null); AnalyzeRule analyzer = new AnalyzeRule(null);
analyzer.setContent(body, baseUrl); analyzer.setContent(body, baseUrl);
//如果符合详情页url规则 //如果符合详情页url规则
if (!isEmpty(bookSource.getInfoRule().getUrlPattern())
initRule(); && baseUrl.matches(bookSource.getInfoRule().getUrlPattern())) {
List<Object> collections; Log.d(tag, ">搜索结果为详情页");
boolean reverse = false; Book item = getItem(analyzer, baseUrl);
boolean allInOne = false; if (item != null) {
if (ruleList.startsWith("-")) { item.putCathe("BookInfoHtml", body);
reverse = true; books.add(item);
ruleList = ruleList.substring(1); }
}
// 仅使用java正则表达式提取书籍列表
if (ruleList.startsWith(":")) {
ruleList = ruleList.substring(1);
Log.d(tag, "┌解析搜索列表");
getBooksOfRegex(body, ruleList.split("&&"), 0, analyzer, books);
} else { } else {
if (ruleList.startsWith("+")) { initRule();
allInOne = true; List<Object> collections;
boolean reverse = false;
boolean allInOne = false;
if (ruleList.startsWith("-")) {
reverse = true;
ruleList = ruleList.substring(1); ruleList = ruleList.substring(1);
} }
//获取列表 // 仅使用java正则表达式提取书籍列表
Log.d(tag, "┌解析搜索列表"); if (ruleList.startsWith(":")) {
collections = analyzer.getElements(ruleList); ruleList = ruleList.substring(1);
if (collections.size() == 0) { Log.d(tag, "┌解析搜索列表");
Log.d(tag, "└搜索列表为空,当做详情页处理"); getBooksOfRegex(body, ruleList.split("&&"), 0, analyzer, books);
Book item = getItem(analyzer, baseUrl);
if (item != null) {
//item.setBookInfoHtml(body);
books.add(item);
}
} else { } else {
Log.d(tag, "└找到 " + collections.size() + " 个匹配的结果"); if (ruleList.startsWith("+")) {
if (allInOne) { allInOne = true;
for (int i = 0; i < collections.size(); i++) { ruleList = ruleList.substring(1);
Object object = collections.get(i); }
Book item = getItemAllInOne(analyzer, object, baseUrl, i == 0); //获取列表
if (item != null) { Log.d(tag, "┌解析搜索列表");
//如果网址相同则缓存 collections = analyzer.getElements(ruleList);
/*if (baseUrl.equals(item.getNoteUrl())) { if (collections.size() == 0 && isEmpty(bookSource.getInfoRule().getUrlPattern())) {
item.setBookInfoHtml(body); Log.d(tag, "└搜索列表为空,当做详情页处理");
}*/ Book item = getItem(analyzer, baseUrl);
books.add(item); if (item != null) {
} item.putCathe("BookInfoHtml", body);
books.add(item);
} }
} else { } else {
for (int i = 0; i < collections.size(); i++) { Log.d(tag, "└找到 " + collections.size() + " 个匹配的结果");
Object object = collections.get(i); if (allInOne) {
analyzer.setContent(object, baseUrl); for (int i = 0; i < collections.size(); i++) {
Book item = getItemInList(analyzer, baseUrl, i == 0); Object object = collections.get(i);
if (item != null) { Book item = getItemAllInOne(analyzer, object, baseUrl, i == 0);
//如果网址相同则缓存 if (item != null) {
/*if (baseUrl.equals(item.getNoteUrl())) { //如果网址相同则缓存
item.setBookInfoHtml(body); if (baseUrl.equals(item.getInfoUrl())) {
}*/ item.putCathe("BookInfoHtml", body);
books.add(item); }
books.add(item);
}
}
} else {
for (int i = 0; i < collections.size(); i++) {
Object object = collections.get(i);
analyzer.setContent(object, baseUrl);
Book item = getItemInList(analyzer, baseUrl, i == 0);
if (item != null) {
//如果网址相同则缓存
if (baseUrl.equals(item.getInfoUrl())) {
item.putCathe("BookInfoHtml", body);
}
books.add(item);
}
} }
} }
} }
} }
} if (books.size() > 1 && reverse) {
if (books.size() > 1 && reverse) { Collections.reverse(books);
Collections.reverse(books); }
} }
if (books.isEmpty()) { if (books.isEmpty()) {
e.onError(new Throwable("未获取到书名")); e.onError(new Throwable("未获取到书名"));
@ -147,7 +156,7 @@ public class BookList {
ruleIntroduce = findRule.getDesc(); ruleIntroduce = findRule.getDesc();
ruleCoverUrl = findRule.getImgUrl(); ruleCoverUrl = findRule.getImgUrl();
ruleLastChapter = findRule.getLastChapter(); ruleLastChapter = findRule.getLastChapter();
ruleNoteUrl = findRule.getTocUrl(); ruleNoteUrl = findRule.getInfoUrl();
} else { } else {
SearchRule searchRule = bookSource.getSearchRule(); SearchRule searchRule = bookSource.getSearchRule();
ruleList = searchRule.getList(); ruleList = searchRule.getList();
@ -157,7 +166,7 @@ public class BookList {
ruleIntroduce = searchRule.getDesc(); ruleIntroduce = searchRule.getDesc();
ruleCoverUrl = searchRule.getImgUrl(); ruleCoverUrl = searchRule.getImgUrl();
ruleLastChapter = searchRule.getLastChapter(); ruleLastChapter = searchRule.getLastChapter();
ruleNoteUrl = searchRule.getTocUrl(); ruleNoteUrl = searchRule.getInfoUrl();
} }
} }
@ -170,8 +179,24 @@ public class BookList {
analyzer.setBook(item); analyzer.setBook(item);
item.setTag(tag); item.setTag(tag);
item.setSource(bookSource.getSourceUrl()); item.setSource(bookSource.getSourceUrl());
item.setChapterUrl(baseUrl);
item.setInfoUrl(baseUrl); item.setInfoUrl(baseUrl);
// 获取详情页预处理规则
String ruleInfoInit = infoRule.getInit();
if (!isEmpty(ruleInfoInit)) {
// 仅使用java正则表达式提取书籍详情
if (ruleInfoInit.startsWith(":")) {
ruleInfoInit = ruleInfoInit.substring(1);
Log.d(tag, "┌详情信息预处理");
AnalyzeByRegex.getInfoOfRegex(String.valueOf(analyzer.getContent()), ruleInfoInit.split("&&"), 0, item, analyzer, bookSource, tag);
if (isEmpty(item.getName())) return null;
return item;
} else {
Object object = analyzer.getElement(ruleInfoInit);
if (object != null) {
analyzer.setContent(object);
}
}
}
Log.d(tag, ">书籍网址:" + baseUrl); Log.d(tag, ">书籍网址:" + baseUrl);
Log.d(tag, "┌获取书名"); Log.d(tag, "┌获取书名");
String bookName = StringUtils.formatHtml(analyzer.getString(infoRule.getName())); String bookName = StringUtils.formatHtml(analyzer.getString(infoRule.getName()));
@ -193,10 +218,6 @@ public class BookList {
Log.d(tag, "┌获取封面"); Log.d(tag, "┌获取封面");
item.setImgUrl(analyzer.getString(infoRule.getImgUrl(), true)); item.setImgUrl(analyzer.getString(infoRule.getImgUrl(), true));
Log.d(tag, "└" + item.getImgUrl()); Log.d(tag, "└" + item.getImgUrl());
Log.d(tag, "┌获取目录网址");
String bookCatalogUrl = analyzer.getString(infoRule.getTocUrl(), true);
if (!isEmpty(bookCatalogUrl)) item.setChapterUrl(bookCatalogUrl);;
Log.d(tag, "└" + item.getChapterUrl());
return item; return item;
} }
return null; return null;
@ -206,7 +227,7 @@ public class BookList {
Book item = new Book(); Book item = new Book();
analyzer.setBook(item); analyzer.setBook(item);
NativeObject nativeObject = (NativeObject) object; NativeObject nativeObject = (NativeObject) object;
if (printLog) Log.d(tag, "┌获取书名"); if (printLog) Log.d(tag, "┌获取书名");
String bookName = StringUtils.formatHtml(String.valueOf(nativeObject.get(ruleName))); String bookName = StringUtils.formatHtml(String.valueOf(nativeObject.get(ruleName)));
if (printLog) Log.d(tag, "└" + bookName); if (printLog) Log.d(tag, "└" + bookName);
if (!isEmpty(bookName)) { if (!isEmpty(bookName)) {
@ -216,24 +237,24 @@ public class BookList {
if (printLog) Log.d(tag, "┌获取作者"); if (printLog) Log.d(tag, "┌获取作者");
item.setAuthor(StringUtils.formatHtml(String.valueOf(nativeObject.get(ruleAuthor)))); item.setAuthor(StringUtils.formatHtml(String.valueOf(nativeObject.get(ruleAuthor))));
if (printLog) Log.d(tag, "└" + item.getAuthor()); if (printLog) Log.d(tag, "└" + item.getAuthor());
if (printLog) Log.d(tag, "┌获取分类"); if (printLog) Log.d(tag, "┌获取分类");
item.setType(String.valueOf(nativeObject.get(ruleKind))); item.setType(String.valueOf(nativeObject.get(ruleKind)));
if (printLog) Log.d(tag,"└" + item.getType()); if (printLog) Log.d(tag, "└" + item.getType());
if (printLog) Log.d(tag, "┌获取最新章节"); if (printLog) Log.d(tag, "┌获取最新章节");
item.setNewestChapterTitle(String.valueOf(nativeObject.get(ruleLastChapter))); item.setNewestChapterTitle(String.valueOf(nativeObject.get(ruleLastChapter)));
if (printLog) Log.d(tag, "└" + item.getNewestChapterTitle()); if (printLog) Log.d(tag, "└" + item.getNewestChapterTitle());
if (printLog) Log.d(tag, "┌获取简介"); if (printLog) Log.d(tag, "┌获取简介");
item.setDesc(String.valueOf(nativeObject.get(ruleIntroduce))); item.setDesc(String.valueOf(nativeObject.get(ruleIntroduce)));
if (printLog) Log.d(tag, "└" + item.getDesc()); if (printLog) Log.d(tag, "└" + item.getDesc());
if (printLog) Log.d(tag, "┌获取封面"); if (printLog) Log.d(tag, "┌获取封面");
if (!isEmpty(ruleCoverUrl)) if (!isEmpty(ruleCoverUrl))
item.setImgUrl(NetworkUtils.getAbsoluteURL(baseUrl, String.valueOf(nativeObject.get(ruleCoverUrl)))); item.setImgUrl(NetworkUtils.getAbsoluteURL(baseUrl, String.valueOf(nativeObject.get(ruleCoverUrl))));
if (printLog) Log.d(tag, "└" + item.getImgUrl()); if (printLog) Log.d(tag, "└" + item.getImgUrl());
if (printLog) Log.d(tag, "┌获取书籍网址"); if (printLog) Log.d(tag, "┌获取书籍网址");
String resultUrl = String.valueOf(nativeObject.get(ruleNoteUrl)); String resultUrl = String.valueOf(nativeObject.get(ruleNoteUrl));
if (isEmpty(resultUrl)) resultUrl = baseUrl; if (isEmpty(resultUrl)) resultUrl = baseUrl;
item.setChapterUrl(resultUrl); item.setInfoUrl(resultUrl);
if (printLog) Log.d(tag, "└" + item.getChapterUrl()); if (printLog) Log.d(tag, "└" + item.getInfoUrl());
return item; return item;
} }
return null; return null;
@ -264,12 +285,12 @@ public class BookList {
if (printLog) Log.d(tag, "└" + item.getDesc()); if (printLog) Log.d(tag, "└" + item.getDesc());
if (printLog) Log.d(tag, "┌获取封面"); if (printLog) Log.d(tag, "┌获取封面");
item.setImgUrl(analyzer.getString(ruleCoverUrl, true)); item.setImgUrl(analyzer.getString(ruleCoverUrl, true));
if (printLog) Log.d(tag, "└" + item.getImgUrl()); if (printLog) Log.d(tag, "└" + item.getImgUrl());
Log.d(tag, "┌获取书籍网址"); Log.d(tag, "┌获取书籍网址");
String resultUrl = analyzer.getString(ruleNoteUrl, true); String resultUrl = analyzer.getString(ruleNoteUrl, true);
if (isEmpty(resultUrl)) resultUrl = baseUrl; if (isEmpty(resultUrl)) resultUrl = baseUrl;
item.setChapterUrl(resultUrl); item.setInfoUrl(resultUrl);
if (printLog) Log.d(tag, "└" + item.getChapterUrl()); if (printLog) Log.d(tag, "└" + item.getInfoUrl());
return item; return item;
} }
return null; return null;
@ -344,12 +365,13 @@ public class BookList {
item.setNewestChapterTitle(ruleVal.get("ruleLastChapter")); item.setNewestChapterTitle(ruleVal.get("ruleLastChapter"));
item.setDesc(ruleVal.get("ruleIntroduce")); item.setDesc(ruleVal.get("ruleIntroduce"));
item.setImgUrl(ruleVal.get("ruleCoverUrl")); item.setImgUrl(ruleVal.get("ruleCoverUrl"));
item.setChapterUrl(NetworkUtils.getAbsoluteURL(baseUrl, ruleVal.get("ruleNoteUrl"))); item.setInfoUrl(NetworkUtils.getAbsoluteURL(baseUrl, ruleVal.get("ruleNoteUrl")));
books.add(item); books.add(item);
// 判断搜索结果是否为详情页 // 判断搜索结果是否为详情页
if (books.size() == 1 && (isEmpty(ruleVal.get("ruleNoteUrl")) || ruleVal.get("ruleNoteUrl").equals(baseUrl))) { if (books.size() == 1 && (isEmpty(ruleVal.get("ruleNoteUrl")) || ruleVal.get("ruleNoteUrl").equals(baseUrl))) {
books.get(0).setChapterUrl(baseUrl); books.get(0).setInfoUrl(baseUrl);
//books.get(0).setBookInfoHtml(res); books.get(0).putCathe("BookInfoHtml", res);
;
return; return;
} }
} while (resM.find()); } while (resM.find());
@ -368,7 +390,7 @@ public class BookList {
Log.d(tag, "┌获取封面"); Log.d(tag, "┌获取封面");
Log.d(tag, "└" + books.get(0).getImgUrl()); Log.d(tag, "└" + books.get(0).getImgUrl());
Log.d(tag, "┌获取书籍"); Log.d(tag, "┌获取书籍");
Log.d(tag, "└" + books.get(0).getChapterUrl()); Log.d(tag, "└" + books.get(0).getInfoUrl());
} else { } else {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
do { do {

@ -47,6 +47,7 @@ import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App; import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.BitIntentDataManager;
import xyz.fycz.myreader.base.observer.MyObserver; import xyz.fycz.myreader.base.observer.MyObserver;
import xyz.fycz.myreader.base.observer.MySingleObserver; import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.APPCONST;
@ -106,7 +107,6 @@ public class BookDetailedActivity extends BaseActivity {
private BookGroupDialog mBookGroupDia; private BookGroupDialog mBookGroupDia;
private List<String> tagList = new ArrayList<>(); private List<String> tagList = new ArrayList<>();
private Disposable chaptersDis; private Disposable chaptersDis;
private boolean thirdSource;
@SuppressLint("HandlerLeak") @SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() { private Handler mHandler = new Handler() {
@ -115,11 +115,13 @@ public class BookDetailedActivity extends BaseActivity {
switch (msg.what) { switch (msg.what) {
case 1: case 1:
if (!"本地书籍".equals(mBook.getType())) { if (!"本地书籍".equals(mBook.getType())) {
initBookInfo();
mChapters.clear(); mChapters.clear();
mNewestChapters.clear(); mNewestChapters.clear();
initBookInfo(); if (!isThirdSource()) {
initChapters(true); initChapters(true);
mCatalogAdapter.notifyDataSetChanged(); }
mCatalogAdapter.clear();
} }
break; break;
case 2: case 2:
@ -154,16 +156,20 @@ public class BookDetailedActivity extends BaseActivity {
super.initData(savedInstanceState); super.initData(savedInstanceState);
mBookService = BookService.getInstance(); mBookService = BookService.getInstance();
mChapterService = ChapterService.getInstance(); mChapterService = ChapterService.getInstance();
aBooks = (ArrayList<Book>) getIntent().getSerializableExtra(APPCONST.SEARCH_BOOK_BEAN); aBooks = (ArrayList<Book>) BitIntentDataManager.getInstance().getData(getIntent());
sourceIndex = getIntent().getIntExtra(APPCONST.SOURCE_INDEX, 0); sourceIndex = getIntent().getIntExtra(APPCONST.SOURCE_INDEX, 0);
if (aBooks != null) { if (aBooks != null) {
mBook = aBooks.get(sourceIndex); mBook = aBooks.get(sourceIndex);
} else { } else {
mBook = (Book) getIntent().getSerializableExtra(APPCONST.BOOK); mBook = (Book) getIntent().getSerializableExtra(APPCONST.BOOK);
} }
if (mBook == null) {
ToastUtils.showError("无法获取书籍!");
finish();
}
isCollected = isBookCollected(); isCollected = isBookCollected();
if (isCollected) { if (isCollected) {
mChapters = (ArrayList<Chapter>) mChapterService.findBookAllChapterByBookId(mBook.getId()); mChapters = mChapterService.findBookAllChapterByBookId(mBook.getId());
} }
//Dialog //Dialog
mSourceDialog = new SourceExchangeDialog(this, mBook); mSourceDialog = new SourceExchangeDialog(this, mBook);
@ -175,7 +181,6 @@ public class BookDetailedActivity extends BaseActivity {
} }
mBookGroupDia = new BookGroupDialog(this); mBookGroupDia = new BookGroupDialog(this);
mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource()); mReadCrawler = ReadCrawlerUtil.getReadCrawler(mBook.getSource());
thirdSource = mReadCrawler instanceof ThirdCrawler;
} }
private void initTagList() { private void initTagList() {
@ -210,7 +215,7 @@ public class BookDetailedActivity extends BaseActivity {
binding.ic.bookDetailRvCatalog.setLayoutManager(new LinearLayoutManager(this)); binding.ic.bookDetailRvCatalog.setLayoutManager(new LinearLayoutManager(this));
binding.ic.bookDetailRvCatalog.setAdapter(mCatalogAdapter); binding.ic.bookDetailRvCatalog.setAdapter(mCatalogAdapter);
if (!thirdSource) initChapters(false); if (!isThirdSource()) initChapters(false);
mCatalogAdapter.setOnItemClickListener((view, pos) -> { mCatalogAdapter.setOnItemClickListener((view, pos) -> {
mBook.setHisttoryChapterNum(mChapters.size() - pos - 1); mBook.setHisttoryChapterNum(mChapters.size() - pos - 1);
@ -328,13 +333,13 @@ public class BookDetailedActivity extends BaseActivity {
if (!StringHelper.isEmpty(bean.getDesc())) { if (!StringHelper.isEmpty(bean.getDesc())) {
bookTem.setDesc(bean.getDesc()); bookTem.setDesc(bean.getDesc());
} }
if (!StringHelper.isEmpty(bean.getUpdateDate())){ if (!StringHelper.isEmpty(bean.getUpdateDate())) {
bookTem.setUpdateDate(bean.getUpdateDate()); bookTem.setUpdateDate(bean.getUpdateDate());
} }
if (!StringHelper.isEmpty(bean.getWordCount())){ if (!StringHelper.isEmpty(bean.getWordCount())) {
bookTem.setWordCount(bean.getWordCount()); bookTem.setWordCount(bean.getWordCount());
} }
if (!StringHelper.isEmpty(bean.getStatus())){ if (!StringHelper.isEmpty(bean.getStatus())) {
bookTem.setStatus(bean.getStatus()); bookTem.setStatus(bean.getStatus());
} }
bookTem.setSource(bean.getSource()); bookTem.setSource(bean.getSource());
@ -372,6 +377,7 @@ public class BookDetailedActivity extends BaseActivity {
public void goToMoreChapter() { public void goToMoreChapter() {
Intent intent = new Intent(this, CatalogActivity.class); Intent intent = new Intent(this, CatalogActivity.class);
intent.putExtra(APPCONST.BOOK, mBook); intent.putExtra(APPCONST.BOOK, mBook);
//BitIntentDataManager.getInstance().putData(intent, mBook);
startActivityForResult(intent, APPCONST.REQUEST_CHAPTER_PAGE); startActivityForResult(intent, APPCONST.REQUEST_CHAPTER_PAGE);
} }
@ -420,7 +426,7 @@ public class BookDetailedActivity extends BaseActivity {
BookSource source = BookSourceManager.getBookSourceByStr(mBook.getSource()); BookSource source = BookSourceManager.getBookSourceByStr(mBook.getSource());
binding.ih.bookDetailSource.setText(String.format("书源:%s", source.getSourceName())); binding.ih.bookDetailSource.setText(String.format("书源:%s", source.getSourceName()));
ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(source); ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(source);
if ((rc instanceof BookInfoCrawler && StringHelper.isEmpty(mBook.getImgUrl())) || thirdSource) { if ((rc instanceof BookInfoCrawler && StringHelper.isEmpty(mBook.getImgUrl())) || isThirdSource()) {
binding.pbLoading.setVisibility(View.VISIBLE); binding.pbLoading.setVisibility(View.VISIBLE);
BookInfoCrawler bic = (BookInfoCrawler) rc; BookInfoCrawler bic = (BookInfoCrawler) rc;
BookApi.getBookInfo(mBook, bic).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver<Book>() { BookApi.getBookInfo(mBook, bic).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver<Book>() {
@ -428,7 +434,7 @@ public class BookDetailedActivity extends BaseActivity {
public void onNext(@NotNull Book book) { public void onNext(@NotNull Book book) {
if (!App.isDestroy(BookDetailedActivity.this)) { if (!App.isDestroy(BookDetailedActivity.this)) {
mHandler.sendMessage(mHandler.obtainMessage(4)); mHandler.sendMessage(mHandler.obtainMessage(4));
if (thirdSource) { if (isThirdSource()) {
initChapters(false); initChapters(false);
} }
} }
@ -439,7 +445,7 @@ public class BookDetailedActivity extends BaseActivity {
public void onError(Throwable e) { public void onError(Throwable e) {
if (!App.isDestroy(BookDetailedActivity.this)) { if (!App.isDestroy(BookDetailedActivity.this)) {
ToastUtils.showError("书籍详情加载失败!"); ToastUtils.showError("书籍详情加载失败!");
if (thirdSource) { if (isThirdSource()) {
initChapters(false); initChapters(false);
} }
binding.pbLoading.setVisibility(View.GONE); binding.pbLoading.setVisibility(View.GONE);
@ -507,8 +513,8 @@ public class BookDetailedActivity extends BaseActivity {
public void onError(Throwable e) { public void onError(Throwable e) {
binding.pbLoading.setVisibility(View.GONE); binding.pbLoading.setVisibility(View.GONE);
mCatalogAdapter.clear(); mCatalogAdapter.clear();
ToastUtils.showError("最新章节加载失败!");
if (App.isDebug()) e.printStackTrace(); if (App.isDebug()) e.printStackTrace();
ToastUtils.showError("最新章节加载失败!\n" + e.getLocalizedMessage());
} }
}); });
} else { } else {
@ -650,6 +656,16 @@ public class BookDetailedActivity extends BaseActivity {
} }
}); });
break; break;
case R.id.action_edit_source:
BookSource source = BookSourceManager.getBookSourceByStr(mBook.getSource());
if (!TextUtils.isEmpty(source.getSourceEName())) {
ToastUtils.showWarring("内置书源无法编辑!");
} else {
Intent sourceIntent = new Intent(this, SourceEditActivity.class);
sourceIntent.putExtra(APPCONST.BOOK_SOURCE, source);
startActivity(sourceIntent);
}
break;
default: default:
break; break;
} }
@ -803,7 +819,6 @@ public class BookDetailedActivity extends BaseActivity {
textPaint.setColor(Color.BLACK); textPaint.setColor(Color.BLACK);
cv.drawText(mBook.getType() == null ? "" : mBook.getType(), margin + marginTop + img.getWidth(), margin + marginTop * 8, textPaint); cv.drawText(mBook.getType() == null ? "" : mBook.getType(), margin + marginTop + img.getWidth(), margin + marginTop * 8, textPaint);
assert mBook.getSource() != null;
cv.drawText("书源:" + BookSourceManager.getSourceNameByStr(mBook.getSource()), margin + marginTop + img.getWidth(), margin + marginTop * 10, textPaint); cv.drawText("书源:" + BookSourceManager.getSourceNameByStr(mBook.getSource()), margin + marginTop + img.getWidth(), margin + marginTop * 10, textPaint);
int textSize = 35; int textSize = 35;
@ -892,4 +907,8 @@ public class BookDetailedActivity extends BaseActivity {
return lines; return lines;
} }
private boolean isThirdSource() {
return mReadCrawler instanceof ThirdCrawler;
}
} }

@ -19,6 +19,7 @@ import java.util.List;
import xyz.fycz.myreader.R; import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App; import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.BitIntentDataManager;
import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.databinding.ActiityBookstoreBinding; import xyz.fycz.myreader.databinding.ActiityBookstoreBinding;
import xyz.fycz.myreader.entity.bookstore.BookType; import xyz.fycz.myreader.entity.bookstore.BookType;
@ -159,7 +160,7 @@ public class BookstoreActivity extends BaseActivity {
mSourceDia = new SourceExchangeDialog(this, book); mSourceDia = new SourceExchangeDialog(this, book);
mSourceDia.setOnSourceChangeListener((bean, pos1) -> { mSourceDia.setOnSourceChangeListener((bean, pos1) -> {
Intent intent = new Intent(this, BookDetailedActivity.class); Intent intent = new Intent(this, BookDetailedActivity.class);
intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, (ArrayList<Book>) mSourceDia.getaBooks()); BitIntentDataManager.getInstance().putData(intent, mSourceDia.getaBooks());
intent.putExtra(APPCONST.SOURCE_INDEX, pos1); intent.putExtra(APPCONST.SOURCE_INDEX, pos1);
BookstoreActivity.this.startActivity(intent); BookstoreActivity.this.startActivity(intent);
mSourceDia.dismiss(); mSourceDia.dismiss();

@ -17,6 +17,7 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
@ -64,11 +65,13 @@ import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.BookMark; import xyz.fycz.myreader.greendao.entity.BookMark;
import xyz.fycz.myreader.greendao.entity.Chapter; import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean; import xyz.fycz.myreader.greendao.entity.ReplaceRuleBean;
import xyz.fycz.myreader.greendao.entity.rule.BookSource;
import xyz.fycz.myreader.greendao.service.BookGroupService; import xyz.fycz.myreader.greendao.service.BookGroupService;
import xyz.fycz.myreader.greendao.service.BookMarkService; import xyz.fycz.myreader.greendao.service.BookMarkService;
import xyz.fycz.myreader.greendao.service.BookService; import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.greendao.service.ChapterService; import xyz.fycz.myreader.greendao.service.ChapterService;
import xyz.fycz.myreader.model.audio.ReadAloudService; import xyz.fycz.myreader.model.audio.ReadAloudService;
import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
import xyz.fycz.myreader.model.storage.Backup; import xyz.fycz.myreader.model.storage.Backup;
import xyz.fycz.myreader.ui.dialog.AudioPlayerDialog; import xyz.fycz.myreader.ui.dialog.AudioPlayerDialog;
import xyz.fycz.myreader.ui.dialog.CopyContentDialog; import xyz.fycz.myreader.ui.dialog.CopyContentDialog;
@ -752,6 +755,15 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
startActivity(intent); startActivity(intent);
} else if (itemId == R.id.action_download) { } else if (itemId == R.id.action_download) {
download(); download();
} else if (itemId == R.id.action_edit_source) {
BookSource source = BookSourceManager.getBookSourceByStr(mBook.getSource());
if (!TextUtils.isEmpty(source.getSourceEName())) {
ToastUtils.showWarring("内置书源无法编辑!");
} else {
Intent sourceIntent = new Intent(this, SourceEditActivity.class);
sourceIntent.putExtra(APPCONST.BOOK_SOURCE, source);
startActivity(sourceIntent);
}
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }

@ -38,6 +38,7 @@ import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App; import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.BitIntentDataManager;
import xyz.fycz.myreader.base.observer.MySingleObserver; import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.databinding.ActivitySearchBookBinding; import xyz.fycz.myreader.databinding.ActivitySearchBookBinding;
@ -546,7 +547,7 @@ public class SearchBookActivity extends BaseActivity {
if (books == null || books.size() == 0) return; if (books == null || books.size() == 0) return;
searchBookBean2Book(data, books.get(0)); searchBookBean2Book(data, books.get(0));
Intent intent = new Intent(this, BookDetailedActivity.class); Intent intent = new Intent(this, BookDetailedActivity.class);
intent.putExtra(APPCONST.SEARCH_BOOK_BEAN, books); BitIntentDataManager.getInstance().putData(intent, books);
startActivity(intent); startActivity(intent);
}); });
binding.srlSearchBookList.setEnableRefresh(true); binding.srlSearchBookList.setEnableRefresh(true);

@ -258,6 +258,7 @@ public class SourceDebugActivity extends BaseActivity {
ListResult listResult = new ListResult(); ListResult listResult = new ListResult();
Book book = new Book(); Book book = new Book();
book.setChapterUrl(debugEntity.getUrl()); book.setChapterUrl(debugEntity.getUrl());
book.setInfoUrl(debugEntity.getUrl());
switch (debugEntity.getDebugMode()) { switch (debugEntity.getDebugMode()) {
case DebugEntity.SEARCH: case DebugEntity.SEARCH:
default: default:

@ -78,7 +78,8 @@ public class SearchBookHolder extends ViewHolderImpl<SearchBookBean> {
public void onBind(SearchBookBean data, int pos) { public void onBind(SearchBookBean data, int pos) {
List<Book> aBooks = mBooks.getValues(data); List<Book> aBooks = mBooks.getValues(data);
if (aBooks == null || aBooks.size() == 0){ if (aBooks == null || aBooks.size() == 0){
return; aBooks = new ArrayList<>();
aBooks.add(searchBookBean2Book(data));
} }
int bookCount = aBooks.size(); int bookCount = aBooks.size();
Book book = aBooks.get(0); Book book = aBooks.get(0);
@ -116,7 +117,7 @@ public class SearchBookHolder extends ViewHolderImpl<SearchBookBean> {
initOtherInfo(data, rc); initOtherInfo(data, rc);
return; return;
} }
Log.i(book.getName(), "initOtherInfo"); Log.i(data.getName(), "initOtherInfo");
BookInfoCrawler bic = (BookInfoCrawler) rc; BookInfoCrawler bic = (BookInfoCrawler) rc;
searchEngine.getBookInfo(book, bic, isSuccess -> { searchEngine.getBookInfo(book, bic, isSuccess -> {
if (isSuccess) { if (isSuccess) {
@ -230,6 +231,19 @@ public class SearchBookHolder extends ViewHolderImpl<SearchBookBean> {
} }
} }
private Book searchBookBean2Book(SearchBookBean bean){
Book book = new Book();
book.setName(bean.getName());
book.setAuthor(bean.getAuthor());
book.setType(bean.getType());
book.setDesc(bean.getDesc());
book.setStatus(bean.getStatus());
book.setUpdateDate(bean.getUpdateTime());
book.setNewestChapterTitle(bean.getLastChapter());
book.setWordCount(bean.getWordCount());
return book;
}
private boolean needGetInfo(SearchBookBean bookBean) { private boolean needGetInfo(SearchBookBean bookBean) {
if (StringHelper.isEmpty(bookBean.getAuthor())) return true; if (StringHelper.isEmpty(bookBean.getAuthor())) return true;
if (StringHelper.isEmpty(bookBean.getType())) return true; if (StringHelper.isEmpty(bookBean.getType())) return true;

@ -5,6 +5,8 @@ import android.text.TextUtils;
import android.util.Base64; import android.util.Base64;
import android.util.Log; import android.util.Log;
import androidx.annotation.Keep;
import org.jsoup.Connection; import org.jsoup.Connection;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
@ -30,7 +32,7 @@ import xyz.fycz.myreader.util.utils.MD5Utils;
import xyz.fycz.myreader.util.utils.OkHttpUtils; import xyz.fycz.myreader.util.utils.OkHttpUtils;
import xyz.fycz.myreader.util.utils.StringUtils; import xyz.fycz.myreader.util.utils.StringUtils;
@SuppressWarnings({"unused", "WeakerAccess"}) @SuppressWarnings({"unused"})
public interface JsExtensions { public interface JsExtensions {
String TAG = JsExtensions.class.getSimpleName(); String TAG = JsExtensions.class.getSimpleName();

@ -123,9 +123,9 @@ public class AdUtils {
public static void initAd() { public static void initAd() {
if (!hasInitAd) { if (!hasInitAd) {
hasInitAd = true; hasInitAd = true;
DdSdkHelper.init("", "", "", DdSdkHelper.init("1234", "216", "51716a16fbdf50905704b6575b1b3b60",
"", "", "142364", "35ce0efe5f3cc960b116db227498e238",
"", "", "8167", "85bd159309c3da1b",
App.getApplication(), App.isDebug()); App.getApplication(), App.isDebug());
} }
} }

@ -54,7 +54,7 @@ object MD5Utils {
if (!file.isFile) { if (!file.isFile) {
return null return null
} }
var digest: MessageDigest? = null val digest: MessageDigest?
var `in`: FileInputStream? = null var `in`: FileInputStream? = null
val buffer = ByteArray(1024) val buffer = ByteArray(1024)
var len: Int var len: Int

@ -19,6 +19,7 @@ import xyz.fycz.myreader.entity.StrResponse;
import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter; import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap; import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.utils.NetworkUtils; import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.OkHttpUtils; import xyz.fycz.myreader.util.utils.OkHttpUtils;
import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
@ -108,6 +109,7 @@ public class BookApi {
return ThirdSourceApi.getBookChaptersByTC(book, (ThirdCrawler) rc); return ThirdSourceApi.getBookChaptersByTC(book, (ThirdCrawler) rc);
} }
String url = book.getChapterUrl(); String url = book.getChapterUrl();
if (StringHelper.isEmpty(url)) url = book.getInfoUrl();
String charset = rc.getCharset(); String charset = rc.getCharset();
url = NetworkUtils.getAbsoluteURL(rc.getNameSpace(), url); url = NetworkUtils.getAbsoluteURL(rc.getNameSpace(), url);
String finalUrl = url; String finalUrl = url;

@ -1,7 +1,10 @@
package xyz.fycz.myreader.webapi; package xyz.fycz.myreader.webapi;
import android.text.TextUtils;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import io.reactivex.Observable; import io.reactivex.Observable;
@ -58,9 +61,9 @@ public class ThirdSourceApi {
protected static Observable<Book> getBookInfoByTC(Book book, ThirdCrawler rc) { protected static Observable<Book> getBookInfoByTC(Book book, ThirdCrawler rc) {
BookSource source = rc.getSource(); BookSource source = rc.getSource();
BookInfo bookInfo = new BookInfo(source.getSourceUrl(), source.getSourceName(), source); BookInfo bookInfo = new BookInfo(source.getSourceUrl(), source.getSourceName(), source);
/*if (!TextUtils.isEmpty(book.getBookInfoBean().getBookInfoHtml())) { if (!TextUtils.isEmpty(book.getCathe("BookInfoHtml"))) {
return bookInfo.analyzeBookInfo(book.getBookInfoBean().getBookInfoHtml(), bookShelfBean); return bookInfo.analyzeBookInfo(book.getCathe("BookInfoHtml"), book);
}*/ }
try { try {
Map<String, String> headers = rc.getHeaders(); Map<String, String> headers = rc.getHeaders();
headers.putAll(getCookies(rc.getNameSpace())); headers.putAll(getCookies(rc.getNameSpace()));
@ -75,13 +78,13 @@ public class ThirdSourceApi {
protected static Observable<List<Chapter>> getBookChaptersByTC(Book book, ThirdCrawler rc) { protected static Observable<List<Chapter>> getBookChaptersByTC(Book book, ThirdCrawler rc) {
BookSource source = rc.getSource(); BookSource source = rc.getSource();
Map<String, String> headers = rc.getHeaders();
headers.putAll(getCookies(rc.getNameSpace()));
BookChapterList bookChapterList = new BookChapterList(source.getSourceUrl(), source, true); BookChapterList bookChapterList = new BookChapterList(source.getSourceUrl(), source, true);
/*if (!TextUtils.isEmpty(bookShelfBean.getBookInfoBean().getChapterListHtml())) { if (!TextUtils.isEmpty(book.getCathe("ChapterListHtml"))) {
return bookChapterList.analyzeChapterList(bookShelfBean.getBookInfoBean().getChapterListHtml(), bookShelfBean, headerMap); return bookChapterList.analyzeChapterList(book.getCathe("ChapterListHtml"), book, headers);
}*/ }
try { try {
Map<String, String> headers = rc.getHeaders();
headers.putAll(getCookies(rc.getNameSpace()));
AnalyzeUrl analyzeUrl = new AnalyzeUrl(book.getChapterUrl(), headers, book.getInfoUrl()); AnalyzeUrl analyzeUrl = new AnalyzeUrl(book.getChapterUrl(), headers, book.getInfoUrl());
return OkHttpUtils.getStrResponse(analyzeUrl) return OkHttpUtils.getStrResponse(analyzeUrl)
.flatMap(response -> OkHttpUtils.setCookie(response, source.getSourceUrl())) .flatMap(response -> OkHttpUtils.setCookie(response, source.getSourceUrl()))
@ -101,14 +104,14 @@ public class ThirdSourceApi {
protected static Observable<String> getChapterContentByTC(Chapter chapter, Book book, ThirdCrawler rc) { protected static Observable<String> getChapterContentByTC(Chapter chapter, Book book, ThirdCrawler rc) {
BookSource source = rc.getSource(); BookSource source = rc.getSource();
Map<String, String> headers = rc.getHeaders();
headers.putAll(getCookies(rc.getNameSpace()));
BookContent bookContent = new BookContent(source.getSourceUrl(), source); BookContent bookContent = new BookContent(source.getSourceUrl(), source);
/*if (Objects.equals(chapterBean.getDurChapterUrl(), bookShelfBean.getBookInfoBean().getChapterUrl()) if (Objects.equals(chapter.getUrl(), book.getChapterUrl())
&& !TextUtils.isEmpty(bookShelfBean.getBookInfoBean().getChapterListHtml())) { && !TextUtils.isEmpty(book.getCathe("ChapterListHtml"))) {
return bookContent.analyzeBookContent(bookShelfBean.getBookInfoBean().getChapterListHtml(), chapterBean, nextChapterBean, bookShelfBean, headerMap); return bookContent.analyzeBookContent(book.getCathe("ChapterListHtml"), chapter, null, book, headers);
}*/ }
try { try {
Map<String, String> headers = rc.getHeaders();
headers.putAll(getCookies(rc.getNameSpace()));
AnalyzeUrl analyzeUrl = new AnalyzeUrl(chapter.getUrl(), headers, book.getChapterUrl()); AnalyzeUrl analyzeUrl = new AnalyzeUrl(chapter.getUrl(), headers, book.getChapterUrl());
String contentRule = source.getContentRule().getContent(); String contentRule = source.getContentRule().getContent();
if (contentRule.startsWith("$") && !contentRule.startsWith("$.")) { if (contentRule.startsWith("$") && !contentRule.startsWith("$.")) {

@ -4,9 +4,6 @@
android:viewportWidth="1024" android:viewportWidth="1024"
android:viewportHeight="1024"> android:viewportHeight="1024">
<path <path
android:fillColor="#FF000000" android:pathData="M438.4,849.1l222.7,-646.7c0.2,-0.5 0.3,-1.1 0.4,-1.6L438.4,849.1zM661.2,168.7h-67.5c-3.4,0 -6.5,2.2 -7.6,5.4L354.7,846c-0.3,0.8 -0.4,1.7 -0.4,2.6 0,4.4 3.6,8 8,8h67.8c3.4,0 6.5,-2.2 7.6,-5.4l0.7,-2.1 223.1,-648.3 7.4,-21.4c0.3,-0.8 0.4,-1.7 0.4,-2.6 -0.1,-4.5 -3.6,-8.1 -8.1,-8.1zM954.6,502.1c-0.8,-1 -1.7,-1.9 -2.7,-2.7l-219,-171.3c-3.5,-2.7 -8.5,-2.1 -11.2,1.4 -1.1,1.4 -1.7,3.1 -1.7,4.9v81.3c0,2.5 1.1,4.8 3.1,6.3l115,90 -115,90c-1.9,1.5 -3.1,3.8 -3.1,6.3v81.3c0,4.4 3.6,8 8,8 1.8,0 3.5,-0.6 4.9,-1.7l219,-171.3c6.9,-5.4 8.2,-15.5 2.7,-22.5zM291.1,328.1l-219,171.3c-1,0.8 -1.9,1.7 -2.7,2.7 -5.4,7 -4.2,17 2.7,22.5l219,171.3c1.4,1.1 3.1,1.7 4.9,1.7 4.4,0 8,-3.6 8,-8v-81.3c0,-2.5 -1.1,-4.8 -3.1,-6.3l-115,-90 115,-90c1.9,-1.5 3.1,-3.8 3.1,-6.3v-81.3c0,-1.8 -0.6,-3.5 -1.7,-4.9 -2.7,-3.5 -7.7,-4.1 -11.2,-1.4z"
android:pathData="M681.1,87.8C717,33.2 766.6,5.9 831.5,14.9c60.6,8.3 102.8,43.6 120.9,101.9 21.1,67.7 -1,123.5 -55.5,167.8 3.7,7.6 7.7,15.5 11.4,23.4 19.5,41.6 32,85.3 37.4,131 8.9,75.6 -0.4,148.9 -29.3,219.4 -30.1,73.3 -76.7,134.1 -139.3,182.6 -36.1,27.9 -75.7,49.5 -118.6,65 -4.1,1.5 -6.2,3.6 -7.8,7.8 -22.4,58.1 -64.2,92.5 -126.2,99.2 -69.5,7.5 -133,-34.2 -155.5,-100.1 -1.1,-3.2 -2.8,-4.8 -5.9,-5.9 -112.8,-41.4 -196.2,-116 -249.5,-223.6 -23.6,-47.7 -37.2,-98.3 -41.7,-151.3 -7.4,-85.9 8.6,-167 48.3,-243.5l1.9,-3.8c-43.9,-33 -66.5,-76.6 -63.7,-131.7 2.3,-43.5 21.2,-79.4 55,-106.9 69.3,-56.4 175.1,-40 223.4,42.1C391.7,64.8 449.2,53.1 509,53c59.7,0 117.1,11.5 172.1,34.8zM656.7,837.8c2.1,-0.8 3.7,-1.5 5.4,-2.2 24.7,-11 48.1,-24.5 69.8,-40.6 56.4,-41.9 98.4,-95.2 125.1,-160.2 24.7,-60.4 33.1,-123.1 25.2,-188 -5.8,-47.5 -20.3,-92.1 -42.9,-134.2 -1.6,-3 -3.4,-3.4 -6.7,-3.3 -13.8,0.4 -27.8,2 -41.3,0.2 -77.8,-10.7 -132.2,-76.6 -129,-155 0.2,-3.8 -1,-5.5 -4.4,-7 -35,-14.9 -71.4,-24.4 -109.3,-28.4 -35.3,-3.7 -70.5,-2.3 -105.5,3.9 -28.6,5.1 -56.2,13.5 -83,24.9 -3.5,1.5 -4.3,3.4 -4.3,7.1 0,9 0.1,18.1 -1.2,26.9 -12,83.2 -86,138.8 -169.2,127.6 -1.6,-0.2 -4.2,1 -5,2.4 -3.7,6.5 -7.2,13.2 -10.3,19.9 -30.6,65.6 -41.9,134.3 -33.2,206.3 5,41.9 16.7,81.8 35.4,119.5 35,70.5 87,125.1 155.7,163.5 11.3,6.3 23,11.6 34.8,17.6 12.5,-75.1 83.1,-126.8 155,-122.6 66.9,3.9 124.7,51.3 138.9,121.7zM292,162c0,-46.7 -38,-84.9 -84.8,-85 -46.7,-0.1 -84.9,37.9 -85.2,84.7 -0.2,46.9 38.2,85.3 85.1,85.3 46.7,-0.1 84.8,-38.2 84.9,-85zM811,247c46.7,0 84.9,-38.1 85,-84.8 0.1,-46.7 -37.9,-84.9 -84.7,-85.1 -46.9,-0.2 -85.3,38.2 -85.3,85.1 0.1,46.7 38.2,84.8 85,84.8zM425,865c0,46.7 38.1,84.9 84.8,85 46.7,0.1 84.9,-37.9 85.1,-84.7 0.2,-46.9 -38.2,-85.3 -85.1,-85.3 -46.7,0.1 -84.8,38.2 -84.8,85z"/> android:fillColor="#ffffff"/>
<path
android:fillColor="#FF000000"
android:pathData="M659,492.9c0,82.3 -66.8,149.1 -149,149.1 -82.3,0 -149.1,-66.9 -149,-149.2 0.1,-82.1 66.7,-148.7 148.8,-148.8 82.3,-0.1 149.1,66.6 149.2,148.9zM595,493.2c0.2,-46.7 -37.9,-85 -84.7,-85.2 -46.7,-0.2 -85,37.7 -85.3,84.5 -0.3,46.9 38,85.4 84.9,85.4 46.7,0.1 84.9,-37.9 85.1,-84.7z"/>
</vector> </vector>

@ -159,8 +159,8 @@
<ImageView <ImageView
android:id="@+id/iv_book_source" android:id="@+id/iv_book_source"
android:layout_width="18dp" android:layout_width="21dp"
android:layout_height="18dp" android:layout_height="21dp"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:src="@drawable/ic_source" android:src="@drawable/ic_source"
@ -171,7 +171,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginStart="20dp" android:layout_marginStart="18dp"
android:layout_toEndOf="@id/iv_book_source" android:layout_toEndOf="@id/iv_book_source"
android:text="@string/book_source_man" android:text="@string/book_source_man"
android:textColor="@color/textSecondary" android:textColor="@color/textSecondary"

@ -44,4 +44,9 @@
android:icon="@drawable/ic_group" android:icon="@drawable/ic_group"
android:title="@string/menu_group_setting" android:title="@string/menu_group_setting"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/action_edit_source"
android:icon="@drawable/ic_source"
android:title="@string/book_source"
app:showAsAction="ifRoom"/>
</menu> </menu>

@ -41,4 +41,10 @@
android:title="@string/menu_open_link" android:title="@string/menu_open_link"
app:showAsAction="never"/> app:showAsAction="never"/>
</group> </group>
<item
android:id="@+id/action_edit_source"
android:icon="@drawable/ic_source"
android:title="@string/book_source"
app:showAsAction="ifRoom"/>
</menu> </menu>

@ -388,7 +388,7 @@
<string name="rule_last_chapter">最新章节规则</string> <string name="rule_last_chapter">最新章节规则</string>
<string name="rule_word_count">字数规则</string> <string name="rule_word_count">字数规则</string>
<string name="rule_status">连载状态规则</string> <string name="rule_status">连载状态规则</string>
<string name="book_url_pattern">书籍URL正则</string> <string name="book_url_pattern">书籍详情URL正则</string>
<string name="rule_book_info_init">预处理规则</string> <string name="rule_book_info_init">预处理规则</string>
<string name="rule_toc_url">目录URL规则</string> <string name="rule_toc_url">目录URL规则</string>
<string name="rule_toc_internal">目录列表区间</string> <string name="rule_toc_internal">目录列表区间</string>
@ -486,6 +486,7 @@
<string name="success">成功</string> <string name="success">成功</string>
<string name="check_host_cookie">正在打开首页,成功自动返回主界面</string> <string name="check_host_cookie">正在打开首页,成功自动返回主界面</string>
<string name="clear_cookie">清除Cookie</string> <string name="clear_cookie">清除Cookie</string>
<string name="book_source">编辑书源</string>
<string-array name="reset_screen_time"> <string-array name="reset_screen_time">

@ -1,2 +1,2 @@
#Fri May 14 22:41:02 CST 2021 #Sat May 15 22:50:54 CST 2021
VERSION_CODE=196 VERSION_CODE=199

Loading…
Cancel
Save