diff --git a/.github/workflows/reader.yml b/.github/workflows/reader.yml
index 6918c10..d204b4d 100644
--- a/.github/workflows/reader.yml
+++ b/.github/workflows/reader.yml
@@ -4,6 +4,7 @@ on:
push:
branches:
- master
+ - dev
jobs:
build:
diff --git a/.gitignore b/.gitignore
index 9ab3b92..ba63cba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
*.iml
.gradle
/local.properties
@@ -8,8 +7,7 @@
/build
/captures
.externalNativeBuild
-=======
->>>>>>> eee131cea39d27218fc7d1c3d641d617d377af42
+keystore
# Compiled class file
*.class
diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml
deleted file mode 100644
index 471bf10..0000000
--- a/.idea/assetWizardSettings.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..7643783
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 61a9130..fb7f4a8 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/copyright/FYReader.xml b/.idea/copyright/FYReader.xml
new file mode 100644
index 0000000..991492f
--- /dev/null
+++ b/.idea/copyright/FYReader.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..0d789ef
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/dictionaries/fengyue.xml b/.idea/dictionaries/fengyue.xml
deleted file mode 100644
index 58d8886..0000000
--- a/.idea/dictionaries/fengyue.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index eb20a8e..ab232b8 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -7,11 +7,13 @@
+
+
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 6560a98..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index eb2873e..b526bd5 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -11,6 +11,11 @@
+
+
+
+
+
@@ -26,5 +31,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index a92f8ed..bba6cb8 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,62 +3,22 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index ba83cda..35e7452 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -5,6 +5,7 @@
+
\ No newline at end of file
diff --git a/.idea/render.experimental.xml b/.idea/render.experimental.xml
new file mode 100644
index 0000000..fe25d78
--- /dev/null
+++ b/.idea/render.experimental.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DialogX/build.gradle b/DialogX/build.gradle
index 00eaade..5da6ecc 100644
--- a/DialogX/build.gradle
+++ b/DialogX/build.gradle
@@ -1,8 +1,24 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
apply plugin: 'com.android.library'
-apply plugin: 'android-maven'
-def siteUrl = 'https://github.com/kongzue/DialogX' //项目在github主页地址
-def gitUrl = 'https://github.com/kongzue/DialogX.git' //Git仓库的地址
+def siteUrl = 'https://github.com/kongzue/DialogX'
group = "com.kongzue.dialogx"
@@ -29,36 +45,6 @@ android {
}
}
-//install {
-// repositories.mavenInstaller {
-// // This generates POM.xml with proper parameters
-// pom {
-// project {
-// packaging 'aar'
-// name 'dialogx'
-// url siteUrl
-// licenses {
-// license {
-// name 'The Apache Software License, Version 2.0'
-// url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
-// }
-// }
-// developers {
-// developer {
-// id 'myzchh'//设置自己ID
-// name 'myzchh'//设置自己名字
-// email 'myzcxhh@live.cn'//设置自己邮箱
-// }
-// }
-// scm {
-// connection gitUrl
-// developerConnection gitUrl
-// url siteUrl
-// }
-// }
-// }
-// }
-//}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
@@ -68,21 +54,6 @@ artifacts {
archives sourcesJar
}
-//Properties properties = new Properties()
-//properties.load(project.rootProject.file('local.properties').newDataInputStream())
-//bintray {
-// user = properties.getProperty("bintray.user")
-// key = properties.getProperty("bintray.apikey")
-// configurations = ['archives']
-// pkg {
-// repo = "maven"
-// name = "dialogX" //项目在JCenter的名字
-// websiteUrl = siteUrl
-// vcsUrl = gitUrl
-// licenses = ["Apache-2.0"]
-// publish = true
-// }
-//}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0+'
diff --git a/DialogX/src/main/AndroidManifest.xml b/DialogX/src/main/AndroidManifest.xml
index 1977b08..8bc7c68 100644
--- a/DialogX/src/main/AndroidManifest.xml
+++ b/DialogX/src/main/AndroidManifest.xml
@@ -1,3 +1,21 @@
+
+
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/DialogX.java b/DialogX/src/main/java/com/kongzue/dialogx/DialogX.java
index f079471..d6aef4d 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/DialogX.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/DialogX.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx;
import android.content.Context;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomDialog.java
index 1bdc856..fa3776d 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomDialog.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomDialog.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.animation.Animator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java
index c4c7c36..04533fa 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/BottomMenu.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.util.Log;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java
index 8e25f7c..eda77a8 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/CustomDialog.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.app.Activity;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/FullScreenDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/FullScreenDialog.java
index 2d83beb..0aae171 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/FullScreenDialog.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/FullScreenDialog.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.animation.Animator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/InputDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/InputDialog.java
index 5d2a5c4..2772054 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/InputDialog.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/InputDialog.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.content.res.Configuration;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java
index 4807f07..7661334 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/MessageDialog.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.animation.Animator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java
index b65051b..815397e 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/PopTip.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.animation.Animator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java
index 8f94db5..a742239 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/TipDialog.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.app.Activity;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java
index 8d6d6aa..367a5df 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/dialogs/WaitDialog.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.dialogs;
import android.animation.Animator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/impl/ActivityLifecycleImpl.java b/DialogX/src/main/java/com/kongzue/dialogx/impl/ActivityLifecycleImpl.java
index a898b8c..c2a39a9 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/impl/ActivityLifecycleImpl.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/impl/ActivityLifecycleImpl.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.impl;
import android.app.Activity;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/impl/AnimatorListenerEndCallBack.java b/DialogX/src/main/java/com/kongzue/dialogx/impl/AnimatorListenerEndCallBack.java
index c0dc335..c2a638b 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/impl/AnimatorListenerEndCallBack.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/impl/AnimatorListenerEndCallBack.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.impl;
import android.animation.Animator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java
index 08f23cf..79d74c2 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseDialog.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
import android.app.Activity;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseOnDialogClickCallback.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseOnDialogClickCallback.java
index c39d368..ced57cd 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseOnDialogClickCallback.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BaseOnDialogClickCallback.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
/**
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BottomMenuListViewTouchEvent.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BottomMenuListViewTouchEvent.java
index 3471e29..6562df6 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BottomMenuListViewTouchEvent.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/BottomMenuListViewTouchEvent.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
import android.view.MotionEvent;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogConvertViewInterface.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogConvertViewInterface.java
index 1ea5c70..2ac1c9c 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogConvertViewInterface.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogConvertViewInterface.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
import android.view.View;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogLifecycleCallback.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogLifecycleCallback.java
index eaec9e3..4193f6d 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogLifecycleCallback.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/DialogLifecycleCallback.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
/**
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBackPressedListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBackPressedListener.java
index 997b615..3050078 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBackPressedListener.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBackPressedListener.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
/**
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBindView.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBindView.java
index fda1a74..219a80d 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBindView.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnBindView.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
import android.view.LayoutInflater;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnDialogButtonClickListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnDialogButtonClickListener.java
index 09896c9..bf6ebd2 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnDialogButtonClickListener.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnDialogButtonClickListener.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
import android.view.View;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnIconChangeCallBack.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnIconChangeCallBack.java
index 6dfd630..af1d2ee 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnIconChangeCallBack.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnIconChangeCallBack.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
import com.kongzue.dialogx.dialogs.BottomMenu;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnInputDialogButtonClickListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnInputDialogButtonClickListener.java
index 5567dc0..e1a53da 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnInputDialogButtonClickListener.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnInputDialogButtonClickListener.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
import android.view.View;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemClickListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemClickListener.java
index 2edb4a8..ff7490c 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemClickListener.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemClickListener.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
/**
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemSelectListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemSelectListener.java
index 855c1bf..f5e532a 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemSelectListener.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnMenuItemSelectListener.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
/**
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnSafeInsetsChangeListener.java b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnSafeInsetsChangeListener.java
index e0fda15..8bb06c4 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnSafeInsetsChangeListener.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/interfaces/OnSafeInsetsChangeListener.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.interfaces;
import android.graphics.Rect;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/style/MaterialStyle.java b/DialogX/src/main/java/com/kongzue/dialogx/style/MaterialStyle.java
index 5a4ef66..4468ae7 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/style/MaterialStyle.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/style/MaterialStyle.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.style;
import android.content.Context;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/BottomDialogTouchEventInterceptor.java b/DialogX/src/main/java/com/kongzue/dialogx/util/BottomDialogTouchEventInterceptor.java
index 8025e3f..df5e74f 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/BottomDialogTouchEventInterceptor.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/BottomDialogTouchEventInterceptor.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util;
import android.animation.ObjectAnimator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/FullScreenDialogTouchEventInterceptor.java b/DialogX/src/main/java/com/kongzue/dialogx/util/FullScreenDialogTouchEventInterceptor.java
index 0f982dd..79edbf5 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/FullScreenDialogTouchEventInterceptor.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/FullScreenDialogTouchEventInterceptor.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util;
import android.animation.ObjectAnimator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/IOSMenuArrayAdapter.java b/DialogX/src/main/java/com/kongzue/dialogx/util/IOSMenuArrayAdapter.java
index 1c38896..a2e3adc 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/IOSMenuArrayAdapter.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/IOSMenuArrayAdapter.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util;
import android.content.Context;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java b/DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java
index f2cd457..684467a 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/InputInfo.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util;
/**
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/NormalMenuArrayAdapter.java b/DialogX/src/main/java/com/kongzue/dialogx/util/NormalMenuArrayAdapter.java
index c7aa364..f866288 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/NormalMenuArrayAdapter.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/NormalMenuArrayAdapter.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util;
import android.content.Context;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java b/DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java
index 96cd131..80828cd 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/TextInfo.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util;
/**
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java b/DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java
index 24b8312..a323700 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/WindowUtil.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util;
import android.app.Activity;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/ActivityScreenShotImageView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/ActivityScreenShotImageView.java
index 5b1f65d..8e63f24 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/ActivityScreenShotImageView.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/ActivityScreenShotImageView.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.content.Context;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BlurView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BlurView.java
index 993fa13..5bccf08 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BlurView.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BlurView.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.content.Context;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogListView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogListView.java
index 556a2d0..1dc5209 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogListView.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogListView.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.content.Context;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogScrollView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogScrollView.java
index c684407..9028e3b 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogScrollView.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/BottomDialogScrollView.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.content.Context;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/DialogXBaseRelativeLayout.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/DialogXBaseRelativeLayout.java
index 1be6476..32ad30f 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/DialogXBaseRelativeLayout.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/DialogXBaseRelativeLayout.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.app.Activity;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/MaxRelativeLayout.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/MaxRelativeLayout.java
index ecefd1a..aea8dff 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/MaxRelativeLayout.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/MaxRelativeLayout.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.animation.ValueAnimator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/NoArticulatedProgressView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/NoArticulatedProgressView.java
index 9899f0d..4566a0f 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/NoArticulatedProgressView.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/NoArticulatedProgressView.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.animation.TimeInterpolator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/ProgressView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/ProgressView.java
index 5c88a0a..3ca1914 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/ProgressView.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/ProgressView.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.animation.TimeInterpolator;
diff --git a/DialogX/src/main/java/com/kongzue/dialogx/util/views/RoundView.java b/DialogX/src/main/java/com/kongzue/dialogx/util/views/RoundView.java
index c457993..aa2f79c 100644
--- a/DialogX/src/main/java/com/kongzue/dialogx/util/views/RoundView.java
+++ b/DialogX/src/main/java/com/kongzue/dialogx/util/views/RoundView.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package com.kongzue.dialogx.util.views;
import android.content.Context;
diff --git a/DialogX/src/main/res/anim/anim_dialogx_bottom_enter.xml b/DialogX/src/main/res/anim/anim_dialogx_bottom_enter.xml
index 815d566..1d5f8bd 100644
--- a/DialogX/src/main/res/anim/anim_dialogx_bottom_enter.xml
+++ b/DialogX/src/main/res/anim/anim_dialogx_bottom_enter.xml
@@ -1,4 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DialogX/src/main/res/drawable/button_dialogx_material_night.xml b/DialogX/src/main/res/drawable/button_dialogx_material_night.xml
index e2f8fb7..2b0a822 100644
--- a/DialogX/src/main/res/drawable/button_dialogx_material_night.xml
+++ b/DialogX/src/main/res/drawable/button_dialogx_material_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/button_dialogx_miui_gray.xml b/DialogX/src/main/res/drawable/button_dialogx_miui_gray.xml
index 30fec5e..832e786 100644
--- a/DialogX/src/main/res/drawable/button_dialogx_miui_gray.xml
+++ b/DialogX/src/main/res/drawable/button_dialogx_miui_gray.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/button_dialogx_miui_gray_night.xml b/DialogX/src/main/res/drawable/button_dialogx_miui_gray_night.xml
index 6577554..ddfeccb 100644
--- a/DialogX/src/main/res/drawable/button_dialogx_miui_gray_night.xml
+++ b/DialogX/src/main/res/drawable/button_dialogx_miui_gray_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_light.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_light.xml
index 505db92..eba74af 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_light.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_light.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_night.xml
index a90496c..25af4e4 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_night.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_bkg_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_light.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_light.xml
index 20c28c3..b11d0d4 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_light.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_light.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_night.xml
index b14a6a7..8a2c14c 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_night.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_bottom_bkg_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_button_light_forword.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_button_light_forword.xml
index 261c420..f527725 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_button_light_forword.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_button_light_forword.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_button_night_forword.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_button_night_forword.xml
index 518437f..ef31a67 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_button_night_forword.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_button_night_forword.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap.xml
index 07c0254..1eb86f1 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap_night.xml
index d41f3a9..c95fd22 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap_night.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_dialogtap_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider.xml
index aa97988..f7e738e 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_menu_split_divider.xml
@@ -1,4 +1,22 @@
+
+
-
+
+
-
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg_night.xml
index e367970..56125a1 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg_night.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_material_poptip_bkg_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_miui_bkg_light.xml b/DialogX/src/main/res/drawable/rect_dialogx_miui_bkg_light.xml
index cbfdb50..fa534e6 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_miui_bkg_light.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_miui_bkg_light.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_miui_bkg_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_miui_bkg_night.xml
index 34584b3..990da9e 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_miui_bkg_night.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_miui_bkg_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_normal.xml b/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_normal.xml
index 9516c1f..0dcea10 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_normal.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_normal.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_normal_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_normal_night.xml
index 3689f9a..f2184bb 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_normal_night.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_normal_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_press.xml b/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_press.xml
index 20fd79f..6cd7c5c 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_press.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_press.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_press_night.xml b/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_press_night.xml
index fac0a17..6b18812 100644
--- a/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_press_night.xml
+++ b/DialogX/src/main/res/drawable/rect_dialogx_miui_button_gray_press_night.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/DialogX/src/main/res/layout/item_dialogx_material_bottom_menu_normal_text.xml b/DialogX/src/main/res/layout/item_dialogx_material_bottom_menu_normal_text.xml
index 70a7bb9..8059d1c 100644
--- a/DialogX/src/main/res/layout/item_dialogx_material_bottom_menu_normal_text.xml
+++ b/DialogX/src/main/res/layout/item_dialogx_material_bottom_menu_normal_text.xml
@@ -1,3 +1,21 @@
+
+
diff --git a/DialogX/src/main/res/layout/layout_dialogx_bottom_material.xml b/DialogX/src/main/res/layout/layout_dialogx_bottom_material.xml
index e5613a4..e0cb5f1 100644
--- a/DialogX/src/main/res/layout/layout_dialogx_bottom_material.xml
+++ b/DialogX/src/main/res/layout/layout_dialogx_bottom_material.xml
@@ -1,4 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DialogX/src/main/res/values/colors.xml b/DialogX/src/main/res/values/colors.xml
index f4a3882..78da168 100644
--- a/DialogX/src/main/res/values/colors.xml
+++ b/DialogX/src/main/res/values/colors.xml
@@ -1,4 +1,22 @@
+
+
#2196F3
diff --git a/DialogX/src/main/res/values/styles.xml b/DialogX/src/main/res/values/styles.xml
index a70d270..661ee75 100644
--- a/DialogX/src/main/res/values/styles.xml
+++ b/DialogX/src/main/res/values/styles.xml
@@ -1,4 +1,22 @@
+
+
diff --git a/README.md b/README.md
index 1e7f73b..a74b372 100644
--- a/README.md
+++ b/README.md
@@ -14,10 +14,10 @@
@@ -62,9 +62,9 @@
-
-
-
+ 微信赞赏码
+ 支付宝收款码
+ QQ收款码
@@ -74,21 +74,21 @@
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
diff --git a/app/build.gradle b/app/build.gradle
index 98d12d4..0d6d0ae 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,11 +1,31 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
apply plugin: 'com.android.application'
-apply plugin: 'org.greenrobot.greendao'//greendao插件dependencies
+apply plugin: 'org.greenrobot.greendao'
apply plugin: 'kotlin-android'
def releaseTime() {
return new Date().format("yy.MMddHH", TimeZone.getTimeZone("GMT+08:00"))
}
+def gitCommits = Integer.parseInt('git rev-list HEAD --count'.execute().text.trim())
+
def getVersionCode() {
def versionCodeFile = file('version_code.properties')
if (versionCodeFile.canRead()) {
@@ -88,23 +108,24 @@ android {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- ndk {
- abiFilters "x86", "armeabi", "armeabi-v7a"
- }
if (keyPropsFile.exists()) {
signingConfig signingConfigs.myConifg
}
- }
- debug {
ndk {
- abiFilters "x86", "armeabi", "armeabi-v7a"
+ abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
+ }
+ debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (keyPropsFile.exists()) {
signingConfig signingConfigs.myConifg
}
- versionNameSuffix "-debug"
+ applicationIdSuffix ".debug"
+ versionNameSuffix "-" + gitCommits
+ ndk {
+ abiFilters "arm64-v8a"
+ }
}
android.applicationVariants.all { variant ->
variant.outputs.all {
@@ -124,6 +145,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+
productFlavors {
}
packagingOptions {
@@ -144,12 +169,16 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(path: ':DialogX')
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'androidx.test.ext:junit:1.1.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
- api 'androidx.core:core-ktx:1.3.0'
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ // androidx
+ implementation "androidx.core:core-ktx:$kotlin_version"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
+ implementation 'androidx.appcompat:appcompat:1.3.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
//anko
def anko_version = '0.10.8'
@@ -157,12 +186,11 @@ dependencies {
implementation "org.jetbrains.anko:anko-sdk27-listeners:$anko_version"
//Glide
- implementation 'com.github.bumptech.glide:glide:4.8.0'
- annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
+ implementation 'com.github.bumptech.glide:glide:4.13.1'
- implementation 'com.squareup.okhttp3:okhttp:3.14.7'
+ implementation 'com.squareup.okhttp3:okhttp:4.9.3'
- implementation 'com.google.code.gson:gson:2.8.5'
+ implementation 'com.google.code.gson:gson:2.9.0'
implementation 'com.journeyapps:zxing-android-embedded:3.5.0'
@@ -170,22 +198,16 @@ dependencies {
implementation 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1'
//JSoup
- implementation 'org.jsoup:jsoup:1.11.3'
- implementation 'cn.wanghaomiao:JsoupXpath:2.4.3'
- implementation 'com.jayway.jsonpath:json-path:2.5.0'
+ implementation 'org.jsoup:jsoup:1.14.3'
+ implementation 'cn.wanghaomiao:JsoupXpath:2.5.1'
+ implementation 'com.jayway.jsonpath:json-path:2.7.0'
//SmartRefreshLayout
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.2'
implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.2'
- implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'
-
- implementation 'uk.co.chrisjenx:calligraphy:2.3.0'
-
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
-
- implementation 'com.google.android.material:material:1.1.0'
+ implementation 'com.google.android.material:material:1.4.0'
//Scroller
implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
@@ -196,7 +218,7 @@ dependencies {
//字符串比较
implementation 'net.ricecode:string-similarity:1.0.0'
- implementation 'com.jayway.jsonpath:json-path:2.4.0'
+ implementation 'com.jayway.jsonpath:json-path:2.7.0'
//RxAndroid
implementation 'io.reactivex.rxjava2:rxjava:2.2.19'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
@@ -226,7 +248,7 @@ dependencies {
//JS
//noinspection GradleDependency
- implementation 'com.github.gedoor:rhino-android:1.3'
+ implementation 'com.github.gedoor:rhino-android:1.6'
//XXPermissions
implementation 'com.github.getActivity:XXPermissions:11.2'
@@ -242,10 +264,44 @@ dependencies {
// https://mvnrepository.com/artifact/net.lingala.zip4j/zip4j
implementation group: 'net.lingala.zip4j', name: 'zip4j', version: '2.9.1'
+
+ //协程
+ def coroutines_version = '1.5.1'
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version")
+
+ //apache
+ implementation('org.apache.commons:commons-text:1.9')
+
+ //DDSDK
+ implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
+ implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
+ implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
+ implementation 'com.lzy.net:okgo:3.0.4'
+ implementation 'com.pangle.cn:ads-sdk-pro:4.2.5.2'
+ implementation('com.facebook.fresco:fresco:0.12.0') {
+ exclude module: 'support-v4'
+ exclude group: 'com.android.support'
+ }
+ implementation('com.facebook.fresco:animated-gif:0.12.0') {
+ exclude module: 'support-v4'
+ exclude group: 'com.android.support'
+ }
+ implementation('com.facebook.fresco:animated-webp:0.12.0') {
+ exclude module: 'support-v4'
+ exclude group: 'com.android.support'
+ }
+ implementation('com.facebook.fresco:webpsupport:0.12.0') {
+ exclude module: 'support-v4'
+ exclude group: 'com.android.support'
+ }
+
+ //https://github.com/fengyuecanzhu/Maple
+ implementation("me.fycz.maple:maple:1.8")
}
greendao {
- schemaVersion 32
+ schemaVersion 35
daoPackage 'xyz.fycz.myreader.greendao.gen'
// targetGenDir 'src/main/java'
}
diff --git a/app/libs/ddsdk-release.aar b/app/libs/ddsdk-release.aar
new file mode 100644
index 0000000..1fb6616
Binary files /dev/null and b/app/libs/ddsdk-release.aar differ
diff --git a/app/libs/dynamic-release.aar b/app/libs/dynamic-release.aar
new file mode 100644
index 0000000..59aa4b8
Binary files /dev/null and b/app/libs/dynamic-release.aar differ
diff --git a/app/release.md b/app/release.md
index e2efcf4..b8caf4c 100644
--- a/app/release.md
+++ b/app/release.md
@@ -1,5 +1,3 @@
-* 1、修复部分机型阅读界面切换日夜间闪退的问题
-* 2、优化搜索界面
-* 3、搜索界面新增书架书籍搜索
-* 4、修复朗读到章节最后一页停止的问题
-* 5、新增QQ频道,建议反馈请到QQ频道进行
\ No newline at end of file
+* 1、修复软件无法打开的问题(超时时间为5s)
+* 2、修复DIY书源重复显示订阅书源的问题
+* 3、优化动态插件加载
\ No newline at end of file
diff --git a/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java b/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java
index 12dbf9b..340bdcf 100644
--- a/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java
+++ b/app/src/androidTest/java/xyz/fycz/myreader/ExampleInstrumentedTest.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader;
import android.content.Context;
diff --git a/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java b/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java
index 06e0838..c6ff372 100644
--- a/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java
+++ b/app/src/androidTest/java/xyz/fycz/myreader/TestAudioPlay.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader;
import androidx.test.ext.junit.runners.AndroidJUnit4;
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 670532b..e9d673b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,31 @@
+
+
+
+
+
+
@@ -38,6 +61,7 @@
+
+
+
+
+
+
diff --git a/app/src/main/assets/PrivacyPolicy.html b/app/src/main/assets/PrivacyPolicy.html
index a270d2d..82d20ef 100644
--- a/app/src/main/assets/PrivacyPolicy.html
+++ b/app/src/main/assets/PrivacyPolicy.html
@@ -1,3 +1,21 @@
+
+
风月读书APP隐私政策
风月读书APP隐私政策
diff --git a/app/src/main/assets/updatelog.fy b/app/src/main/assets/updatelog.fy
index 33539ec..f399522 100644
--- a/app/src/main/assets/updatelog.fy
+++ b/app/src/main/assets/updatelog.fy
@@ -1,3 +1,86 @@
+风月读书v2.4.5
+更新内容:
+1、修复书籍无法导出缓存的问题
+
+2022.04.24
+风月读书v2.4.4
+更新内容:
+1、修复软件无法打开的问题(超时时间为5s)
+2、修复DIY书源重复显示订阅书源的问题
+3、优化动态插件加载
+
+2022.03.29
+风月读书v2.4.3
+更新内容:
+1、修复存在同名章节时后面章节内容加载前面章节的问题
+2、修复启动页面加载超时的问题
+3、新增动态插件
+
+2022.03.25
+风月读书v2.4.2
+更新内容:
+1、修复代理问题
+2、修复书源debug闪退问题
+3、修复日志无法上传问题
+4、修改部分URL
+
+2022.03.24
+风月读书v2.4.1
+更新内容:
+1、新增软件代理设置
+2、新增设置切换动画
+3、订阅书源支持编辑
+4、书源订阅支持备份\恢复
+5、修复已知bug
+6、用户中心新增免广告服务
+注:兑换码获取途径:1、从4月份开始,每月将在QQ频道发放(当月有效);2、反馈bug\提出有效建议;3、捐赠获取(带截图私聊作者,之前捐赠的用户也一样)
+
+2022.03.04
+风月读书v2.4.0-beta
+更新内容:
+1、新增用户中心
+2、修复v2.3.9版本搜索界面书源分组显示错位的问题
+
+2022.03.03
+风月读书v2.3.9-beta
+更新内容:
+1、新增书源订阅功能,移除内置书源,原内置书源界面改为订阅书源(订阅书源全部搜集自网络,每月更新)
+2、新增去除广告功能
+3、设置新增我的界面显示方式
+4、修复已知bug
+注:此为beta版本,可能存在未知bug
+
+2022.02.23
+风月读书v2.3.8
+更新内容:
+1、部分设备兼容性适配
+2、尝试解决搜索卡死的问题
+3、修复部分已知bug
+
+2022.02.17
+风月读书v2.3.7
+更新内容:
+1、新增邮箱登录
+2、新增开屏广告
+3、支持作者界面新增广告支持作者
+注:由于广告投放次数的需要,此次更新为强制更新
+
+2022.02.07
+风月读书v2.3.6
+更新内容:
+1、修复第三方书源书籍更新后未读章节提示不高亮的问题
+2、修复日夜间切换闪退bug
+3、修复部分发现无法加载下一页的问题
+4、新增应用崩溃记录界面
+5、书源网络支持蓝奏云文件链接(如有密码,用逗号隔开)
+
+2022.01.21
+风月读书v2.3.4
+更新内容:
+1、兼容第三方书源3.0版本(注意:需要重新导入书源)
+2、修复已知bug
+3、优化部分功能
+
2022.01.17
风月读书v2.3.2
更新内容:
diff --git a/app/src/main/java/xyz/fycz/myreader/ActivityManage.java b/app/src/main/java/xyz/fycz/myreader/ActivityManage.java
index cbfd3f9..2553d8c 100644
--- a/app/src/main/java/xyz/fycz/myreader/ActivityManage.java
+++ b/app/src/main/java/xyz/fycz/myreader/ActivityManage.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader;
import androidx.appcompat.app.AppCompatActivity;
@@ -9,6 +27,8 @@ public class ActivityManage {
private static ArrayList activities = new ArrayList<>();
+ public static int mResumeActivityCount = 0;
+
public static void addActivity(AppCompatActivity activity){
activities.add(activity);
}
diff --git a/app/src/main/java/xyz/fycz/myreader/application/App.java b/app/src/main/java/xyz/fycz/myreader/application/App.java
index c033b7c..099676c 100644
--- a/app/src/main/java/xyz/fycz/myreader/application/App.java
+++ b/app/src/main/java/xyz/fycz/myreader/application/App.java
@@ -1,7 +1,24 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.application;
-import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
@@ -34,34 +51,37 @@ import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.File;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
+import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
import io.reactivex.internal.functions.Functions;
import io.reactivex.plugins.RxJavaPlugins;
+import kotlin.Unit;
+import kotlin.coroutines.Continuation;
+import kotlin.jvm.functions.Function3;
+import kotlinx.coroutines.CoroutineScope;
+import xyz.fycz.dynamic.AppParam;
+import xyz.fycz.dynamic.IAppLoader;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.entity.Setting;
+import xyz.fycz.myreader.entity.lanzou.LanZouFile;
import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
-import xyz.fycz.myreader.ui.activity.MainActivity;
+import xyz.fycz.myreader.model.user.User;
+import xyz.fycz.myreader.model.user.UserService;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
-import xyz.fycz.myreader.ui.fragment.BookcaseFragment;
-import xyz.fycz.myreader.util.help.SSLSocketClient;
+import xyz.fycz.myreader.ui.dialog.UpdateDialog;
import xyz.fycz.myreader.util.SharedPreUtils;
-import xyz.fycz.myreader.util.help.StringHelper;
import xyz.fycz.myreader.util.ToastUtils;
-import xyz.fycz.myreader.util.utils.FileUtils;
+import xyz.fycz.myreader.util.help.SSLSocketClient;
+import xyz.fycz.myreader.util.help.StringHelper;
+import xyz.fycz.myreader.util.utils.AdUtils;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.OkHttpUtils;
-import xyz.fycz.myreader.ui.dialog.UpdateDialog;
+import xyz.fycz.myreader.util.utils.PluginUtils;
+import xyz.fycz.myreader.webapi.LanZouApi;
public class App extends Application {
@@ -71,6 +91,7 @@ public class App extends Application {
private static App application;
private ExecutorService mFixedThreadPool;
private static boolean debug;
+ public static boolean isBackground = false;
@Override
public void onCreate() {
@@ -78,7 +99,6 @@ public class App extends Application {
application = this;
debug = isApkInDebug(this);
CrashHandler.register(this);
- firstInit();
SSLSocketClient.trustAllHosts();//信任所有证书
RxJavaPlugins.setErrorHandler(Functions.emptyConsumer());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@@ -91,7 +111,6 @@ public class App extends Application {
.readTimeout(15_000) // set read timeout.
))
.commit();
-// handleSSLHandshake();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel();
}
@@ -99,17 +118,11 @@ public class App extends Application {
initNightTheme();
// LLog.init(APPCONST.LOG_DIR);
initDialogX();
+ //AdUtils.initAd();
+ PluginUtils.INSTANCE.init();
}
- private void firstInit() {
- SharedPreUtils sru = SharedPreUtils.getInstance();
- if (!sru.getBoolean("firstInit")) {
- BookSourceManager.initDefaultSources();
- sru.putBoolean("firstInit", true);
- }
- }
-
private void initDialogX() {
DialogX.init(this);
DialogX.DEBUGMODE = debug;
@@ -152,31 +165,6 @@ public class App extends Application {
App.getApplication().initNightTheme();
}
- @SuppressLint("TrulyRandom")
- public static void handleSSLHandshake() {
- try {
- TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] certs, String authType) {
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] certs, String authType) {
- }
- }};
-
- SSLContext sc = SSLContext.getInstance("SSL");
- sc.init(null, trustAllCerts, new SecureRandom());
- HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
- HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
- } catch (Exception ignored) {
- }
- }
-
public static Context getmContext() {
return application;
@@ -321,29 +309,29 @@ public class App extends Application {
isForceUpdate = Boolean.parseBoolean(contents[1].substring(contents[1].indexOf(":") + 1));
downloadLink = contents[2].substring(contents[2].indexOf(":") + 1).trim();
updateContent = contents[3].substring(contents[3].indexOf(":") + 1);
- SharedPreUtils spu = SharedPreUtils.getInstance();
- spu.putString(getmContext().getString(R.string.lanzousKeyStart), contents[4].substring(contents[4].indexOf(":") + 1));
+ SharedPreUtils.getInstance().putString(getmContext().getString(R.string.lanzousKeyStart), contents[4].substring(contents[4].indexOf(":") + 1));
String newSplashTime = contents[5].substring(contents[5].indexOf(":") + 1);
- String oldSplashTime = spu.getString("splashTime");
- spu.putBoolean("needUdSI", !oldSplashTime.equals(newSplashTime));
- spu.putString("splashTime", contents[5].substring(contents[5].indexOf(":") + 1));
- spu.putString("splashImageUrl", contents[6].substring(contents[6].indexOf(":") + 1));
- spu.putString("splashImageMD5", contents[7].substring(contents[7].indexOf(":") + 1));
+ String oldSplashTime = SharedPreUtils.getInstance().getString("splashTime");
+ SharedPreUtils.getInstance().putBoolean("needUdSI", !oldSplashTime.equals(newSplashTime));
+ SharedPreUtils.getInstance().putString("splashTime", contents[5].substring(contents[5].indexOf(":") + 1));
+ SharedPreUtils.getInstance().putString("splashImageUrl", contents[6].substring(contents[6].indexOf(":") + 1));
+ SharedPreUtils.getInstance().putString("splashImageMD5", contents[7].substring(contents[7].indexOf(":") + 1));
forceUpdateVersion = Integer.parseInt(contents[8].substring(contents[8].indexOf(":") + 1));
- spu.putInt("forceUpdateVersion", forceUpdateVersion);
+ SharedPreUtils.getInstance().putInt("forceUpdateVersion", forceUpdateVersion);
String domain = contents[9].substring(contents[9].indexOf(":") + 1);
- spu.putString("domain", domain);
-
+ SharedPreUtils.getInstance().putString("domain", domain);
+ String pluginConfigUrl = contents[10].substring(contents[10].indexOf(":") + 1);
+ SharedPreUtils.getInstance().putString("pluginConfigUrl", pluginConfigUrl);
int versionCode = getVersionCode();
isForceUpdate = isForceUpdate && forceUpdateVersion > versionCode;
if (!StringHelper.isEmpty(downloadLink)) {
- spu.putString(getmContext().getString(R.string.downloadLink), downloadLink);
+ SharedPreUtils.getInstance().putString(getmContext().getString(R.string.downloadLink), downloadLink);
} else {
- spu.putString(getmContext().getString(R.string.downloadLink), URLCONST.APP_DIR_UR);
+ SharedPreUtils.getInstance().putString(getmContext().getString(R.string.downloadLink), URLCONST.APP_DIR_URL);
}
String[] updateContents = updateContent.split("/");
for (String string : updateContents) {
@@ -395,7 +383,7 @@ public class App extends Application {
private void goDownload(Activity activity, String url) {
String downloadLink = url;
if (url == null || "".equals(url)) {
- downloadLink = URLCONST.APP_DIR_UR;
+ downloadLink = URLCONST.APP_DIR_URL;
}
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
@@ -407,6 +395,9 @@ public class App extends Application {
* 判断当前应用是否是debug状态
*/
public static boolean isApkInDebug(Context context) {
+ User user = UserService.INSTANCE.readConfig();
+ if (user != null && "fengyue".equals(user.getUserName()))
+ return true;
try {
ApplicationInfo info = context.getApplicationInfo();
return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
@@ -476,4 +467,5 @@ public class App extends Application {
public ExecutorService getmFixedThreadPool() {
return mFixedThreadPool;
}
+
}
diff --git a/app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java b/app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java
index e9c2ecb..0bd930d 100644
--- a/app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java
+++ b/app/src/main/java/xyz/fycz/myreader/application/CrashHandler.java
@@ -1,10 +1,26 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
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;
@@ -12,33 +28,21 @@ 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.File;
-import java.io.IOException;
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 io.reactivex.Observable;
-import io.reactivex.ObservableSource;
-import io.reactivex.functions.Function;
import xyz.fycz.myreader.common.APPCONST;
-import xyz.fycz.myreader.common.URLCONST;
-import xyz.fycz.myreader.ui.activity.SplashActivity;
+import xyz.fycz.myreader.ui.activity.CrashActivity;
+import xyz.fycz.myreader.ui.activity.RestartActivity;
import xyz.fycz.myreader.util.utils.FileUtils;
-import xyz.fycz.myreader.util.utils.OkHttpUtils;
/**
* @author fengyue
@@ -46,7 +50,15 @@ import xyz.fycz.myreader.util.utils.OkHttpUtils;
*/
public final class CrashHandler implements Thread.UncaughtExceptionHandler {
- private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+ private final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.getDefault());
+ /**
+ * Crash 文件名
+ */
+ private static final String CRASH_FILE_NAME = "crash_file";
+ /**
+ * Crash 时间记录
+ */
+ private static final String KEY_CRASH_TIME = "key_crash_time";
/**
* 注册 Crash 监听
@@ -70,7 +82,24 @@ public final class CrashHandler implements Thread.UncaughtExceptionHandler {
@SuppressLint("ApplySharedPref")
@Override
public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
- saveCrashLog(throwable);
+
+ SharedPreferences sharedPreferences = mApplication.getSharedPreferences(CRASH_FILE_NAME, Context.MODE_PRIVATE);
+ long currentCrashTime = System.currentTimeMillis();
+ long lastCrashTime = sharedPreferences.getLong(KEY_CRASH_TIME, 0);
+ // 记录当前崩溃的时间,以便下次崩溃时进行比对
+ sharedPreferences.edit().putLong(KEY_CRASH_TIME, currentCrashTime).commit();
+
+ String logFilePath = saveCrashLog(throwable);
+
+ // 致命异常标记:如果上次崩溃的时间距离当前崩溃小于 5 分钟,那么判定为致命异常
+ boolean deadlyCrash = currentCrashTime - lastCrashTime < 1000 * 60 * 5;
+ // 如果是致命的异常,或者是调试模式下
+ if (deadlyCrash || App.isDebug()) {
+ CrashActivity.start(mApplication, throwable, logFilePath);
+ } else {
+ RestartActivity.Companion.start(mApplication);
+ }
+
// 不去触发系统的崩溃处理(com.android.internal.os.RuntimeInit$KillApplicationHandler)
if (mNextHandler != null && !mNextHandler.getClass().getName().startsWith("com.android.internal.os")) {
mNextHandler.uncaughtException(thread, throwable);
@@ -80,7 +109,7 @@ public final class CrashHandler implements Thread.UncaughtExceptionHandler {
System.exit(10);
}
- private void saveCrashLog(Throwable throwable) {
+ private String saveCrashLog(Throwable throwable) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
throwable.printStackTrace(printWriter);
@@ -142,6 +171,7 @@ public final class CrashHandler implements Thread.UncaughtExceptionHandler {
String path = APPCONST.LOG_DIR + fileName;
File file = FileUtils.getFile(path);
FileUtils.writeText(mPhoneInfo + "\n\n" + mStackTrace, file);
+ return file.getAbsolutePath();
}
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java
index d6ea789..6b6d879 100644
--- a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java
+++ b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.application;
import android.util.Log;
@@ -7,13 +25,17 @@ import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.enums.BookcaseStyle;
import xyz.fycz.myreader.enums.LocalBookSource;
+import xyz.fycz.myreader.greendao.entity.rule.BookSource;
import xyz.fycz.myreader.greendao.service.BookGroupService;
+import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
import xyz.fycz.myreader.util.CacheHelper;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import static xyz.fycz.myreader.application.App.getVersionCode;
+import java.util.List;
+
public class SysManager {
@@ -137,7 +159,12 @@ public class SysManager {
case 6:
SharedPreUtils.getInstance().putString(App.getmContext().getString(R.string.searchSource), "");
Log.d("SourceVersion", "" + 5);
- break;
+ case 7:
+ List sources = BookSourceManager.getAllLocalSource();
+ for (BookSource source : sources){
+ source.setEnable(false);
+ }
+ BookSourceManager.addBookSource(sources);
}
setting.setSourceVersion(APPCONST.SOURCE_VERSION);
saveSetting(setting);
diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java
index 5896d4f..68bb01b 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base;
import android.annotation.SuppressLint;
@@ -5,6 +23,7 @@ import android.content.Intent;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -26,21 +45,26 @@ import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.application.CrashHandler;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.entity.Setting;
+import xyz.fycz.myreader.ui.activity.SplashActivity;
import xyz.fycz.myreader.util.StatusBarUtil;
+import xyz.fycz.myreader.util.utils.AdUtils;
/**
* @author fengyue
* @date 2020/8/12 20:02
*/
-public abstract class BaseActivity extends SwipeBackActivity {
+public abstract class BaseActivity extends SwipeBackActivity {
private static final int INVALID_VAL = -1;
+ protected VB binding;
+
protected static final String INTENT = "intent";
protected CompositeDisposable mDisposable;
protected Toolbar mToolbar;
+
/****************************abstract area*************************************/
/**
* 绑定视图
@@ -150,6 +174,33 @@ public abstract class BaseActivity extends SwipeBackActivity {
}
}
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ AdUtils.backTime();
+ ActivityManage.mResumeActivityCount--;
+ if (ActivityManage.mResumeActivityCount <= 0
+ && !App.isBackground){
+ App.isBackground = true;
+ Log.d("FYReader", "onActivityStarted: 应用进入后台");
+ }
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ ActivityManage.mResumeActivityCount++;
+ if (ActivityManage.mResumeActivityCount == 1 &&
+ App.isBackground) {
+ App.isBackground = false;
+ Log.d("FYReader", "onActivityStarted: 应用进入前台");
+ if (!(this instanceof SplashActivity) && AdUtils.backSplashAd()) {
+ SplashActivity.start(this);
+ }
+ }
+ }
+
@Override
protected void onResume() {
super.onResume();
diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseFragment.java b/app/src/main/java/xyz/fycz/myreader/base/BaseFragment.java
index 0b3a0de..603bfd7 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/BaseFragment.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/BaseFragment.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base;
import android.os.Bundle;
diff --git a/app/src/main/java/xyz/fycz/myreader/base/BasePresenter.java b/app/src/main/java/xyz/fycz/myreader/base/BasePresenter.java
index 984f059..1180470 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/BasePresenter.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/BasePresenter.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base;
diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseTabActivity.java b/app/src/main/java/xyz/fycz/myreader/base/BaseTabActivity.java
index 4a506d4..af3a5d8 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/BaseTabActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/BaseTabActivity.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base;
@@ -17,7 +35,7 @@ import xyz.fycz.myreader.R;
* @date 2020/8/12 20:02
*/
-public abstract class BaseTabActivity extends BaseActivity {
+public abstract class BaseTabActivity extends BaseActivity {
/**************View***************/
protected TabLayout mTlIndicator;
protected ViewPager mVp;
diff --git a/app/src/main/java/xyz/fycz/myreader/base/BitIntentDataManager.java b/app/src/main/java/xyz/fycz/myreader/base/BitIntentDataManager.java
index 3926a28..8a94c91 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/BitIntentDataManager.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/BitIntentDataManager.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base;
import android.content.Intent;
diff --git a/app/src/main/java/xyz/fycz/myreader/base/LazyFragment.kt b/app/src/main/java/xyz/fycz/myreader/base/LazyFragment.kt
index 8f4c625..f738ad3 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/LazyFragment.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/LazyFragment.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base
import android.os.Bundle
diff --git a/app/src/main/java/xyz/fycz/myreader/base/MyTextWatcher.kt b/app/src/main/java/xyz/fycz/myreader/base/MyTextWatcher.kt
index 41768db..3a2c152 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/MyTextWatcher.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/MyTextWatcher.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base
import android.text.TextWatcher
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java b/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java
index d550a1d..4b4cae0 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java
@@ -1,11 +1,31 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter;
-import android.os.Handler;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
+import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
@@ -20,17 +40,34 @@ import java.util.List;
public abstract class BaseListAdapter extends RecyclerView.Adapter implements Filterable {
private static final String TAG = "BaseListAdapter";
+ protected static final int TYPE_OTHER = Integer.MIN_VALUE;
/*common statement*/
protected List mList = new ArrayList<>();
+ protected SparseArray otherViews = new SparseArray<>();
+ protected SparseIntArray otherViewPos = new SparseIntArray();
protected OnItemClickListener mClickListener;
protected OnItemLongClickListener mLongClickListener;
/************************abstract area************************/
protected abstract IViewHolder createViewHolder(int viewType);
+
/*************************rewrite logic area***************************************/
+
+ @Override
+ public int getItemViewType(int position) {
+ int key = otherViewPos.indexOfKey(position);
+ if (key >= 0) {
+ return otherViewPos.valueAt(key);
+ }
+ return super.getItemViewType(position);
+ }
+
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if (viewType < TYPE_OTHER + getOtherCount()) {
+ return new OtherViewHolder(otherViews.get(viewType));
+ }
IViewHolder viewHolder = createViewHolder(viewType);
View view = viewHolder.createItemView(parent);
@@ -41,6 +78,7 @@ public abstract class BaseListAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter extends RecyclerView.Adapter values) {
int oldSize = getItemSize();
if (mList.addAll(values)) {
@@ -122,7 +171,7 @@ public abstract class BaseListAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter= 0 && oldPos < size && newPos >=0 && newPos < size){
+ if (oldPos >= 0 && oldPos < size && newPos >= 0 && newPos < size) {
Collections.swap(mList, oldPos, newPos);
notifyItemMoved(oldPos, newPos);
}
@@ -174,4 +223,11 @@ public abstract class BaseListAdapter extends RecyclerView.Adapter .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter;
import android.view.View;
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter/IViewHolder.java b/app/src/main/java/xyz/fycz/myreader/base/adapter/IViewHolder.java
index c8ba71b..832471c 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter/IViewHolder.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter/IViewHolder.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter;
import android.view.View;
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java b/app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java
index 5136fe0..56fd483 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter;
import android.content.Context;
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/Click.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/Click.kt
index 6da1832..bcf4b22 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/Click.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/Click.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/DiffRecyclerAdapter.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/DiffRecyclerAdapter.kt
index a655868..e7821b4 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/DiffRecyclerAdapter.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/DiffRecyclerAdapter.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2
import android.content.Context
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/ItemAnimation.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/ItemAnimation.kt
index 97746a1..dfc3c15 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/ItemAnimation.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/ItemAnimation.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2
import android.view.animation.Interpolator
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/ItemViewHolder.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/ItemViewHolder.kt
index ddf4555..70b95d3 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/ItemViewHolder.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/ItemViewHolder.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2
import androidx.recyclerview.widget.RecyclerView
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/RecyclerAdapter.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/RecyclerAdapter.kt
index 07806b1..8cab3d4 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/RecyclerAdapter.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/RecyclerAdapter.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2
import android.content.Context
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/AlphaInAnimation.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/AlphaInAnimation.kt
index 3e6e6b5..cebd2be 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/AlphaInAnimation.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/AlphaInAnimation.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2.animations
import android.animation.Animator
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/BaseAnimation.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/BaseAnimation.kt
index 45d0fa5..cb60086 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/BaseAnimation.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/BaseAnimation.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2.animations
import android.animation.Animator
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/ScaleInAnimation.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/ScaleInAnimation.kt
index b398460..6b067f3 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/ScaleInAnimation.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/ScaleInAnimation.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2.animations
import android.animation.Animator
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInBottomAnimation.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInBottomAnimation.kt
index e57b04c..eb803b3 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInBottomAnimation.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInBottomAnimation.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2.animations
import android.animation.Animator
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInLeftAnimation.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInLeftAnimation.kt
index 0d4b69b..ed799a7 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInLeftAnimation.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInLeftAnimation.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2.animations
import android.animation.Animator
diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInRightAnimation.kt b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInRightAnimation.kt
index db4ccf0..6e5b0fa 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInRightAnimation.kt
+++ b/app/src/main/java/xyz/fycz/myreader/base/adapter2/animations/SlideInRightAnimation.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.adapter2.animations
import android.animation.Animator
diff --git a/app/src/main/java/xyz/fycz/myreader/base/observer/MyObserver.java b/app/src/main/java/xyz/fycz/myreader/base/observer/MyObserver.java
index 633e8a8..957cc02 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/observer/MyObserver.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/observer/MyObserver.java
@@ -1,4 +1,20 @@
-//Copyright (c) 2017. 章钦豪. All rights reserved.
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
package xyz.fycz.myreader.base.observer;
import io.reactivex.Observer;
diff --git a/app/src/main/java/xyz/fycz/myreader/base/observer/MySingleObserver.java b/app/src/main/java/xyz/fycz/myreader/base/observer/MySingleObserver.java
index 154b9cb..4b2fc50 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/observer/MySingleObserver.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/observer/MySingleObserver.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.base.observer;
import io.reactivex.SingleObserver;
diff --git a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
index 5077c34..0250f26 100644
--- a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
+++ b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
@@ -1,6 +1,25 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.common;
import android.os.Environment;
+import android.provider.Settings;
import com.google.gson.reflect.TypeToken;
import com.hjq.permissions.Permission;
@@ -43,6 +62,8 @@ public class APPCONST {
+ "book_cache" + File.separator;
public static String HTML_CACHE_PATH = FileUtils.getCachePath() + File.separator
+ "html_cache" + File.separator;
+ public static String PLUGIN_DIR_PATH = App.getmContext().getFilesDir().getParent()
+ + File.separator + "plugin" + File.separator;
public static long exitTime;
public static final int exitConfirmTime = 2000;
@@ -51,6 +72,7 @@ public class APPCONST {
public static final String XPATH = "Xpath";
public static final String JSON_PATH = "JsonPath";
public static final String THIRD_SOURCE = "ThirdSource";
+ public static final String THIRD_3_SOURCE = "Third3Source";
public static final String DATA_KEY = "data_key";
public static final String FIND_CRAWLER = "findCrawler";
@@ -100,6 +122,10 @@ public class APPCONST {
public static final int REQUEST_GROUP_MANAGER = 1014;
public static final int REQUEST_SEARCH_WORD = 1015;
public static final int REQUEST_AUTH_EMAIL = 1016;
+ public static final int REQUEST_SETTING = 1017;
+ public static final int REQUEST_SUBSCRIBE = 1018;
+ public static final int REQUEST_LOGOUT = 1019;
+ public static final int REQUEST_RESET_PWD = 1020;
public static final int REQUEST_READ = 1;
@@ -110,7 +136,7 @@ public class APPCONST {
//设置版本号
public static final int SETTING_VERSION = 11;
- public static final int SOURCE_VERSION = 7;
+ public static final int SOURCE_VERSION = 8;
public static final String FORMAT_FILE_DATE = "yyyy-MM-dd";
@@ -125,6 +151,7 @@ public class APPCONST {
}.getType();
public static final Pattern JS_PATTERN = Pattern.compile("([\\w\\W]*? |@js:[\\w\\W]*$)", Pattern.CASE_INSENSITIVE);
+ public static final Pattern JS_PATTERN_3 = Pattern.compile("([\\w\\W]*?) |@js:([\\w\\W]*)", Pattern.CASE_INSENSITIVE);
public static final Pattern EXP_PATTERN = Pattern.compile("\\{\\{([\\w\\W]*?)\\}\\}");
// public static final Pattern IMG_PATTERN = Pattern.compile(" ", Pattern.CASE_INSENSITIVE);
@@ -132,4 +159,11 @@ public class APPCONST {
public static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4168.3 Safari/537.36";
+ public static final String UA_NAME = "User-Agent";
+
+ public static final String androidId = getAndroidId();
+
+ public static String getAndroidId() {
+ return Settings.System.getString(App.getmContext().getContentResolver(), Settings.Secure.ANDROID_ID);
+ }
}
diff --git a/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java b/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java
index f244c8b..b3375ae 100644
--- a/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java
+++ b/app/src/main/java/xyz/fycz/myreader/common/URLCONST.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.common;
import xyz.fycz.myreader.util.SharedPreUtils;
@@ -6,9 +24,11 @@ public class URLCONST {
public static final String OFFICIAL_WEB = "https://reader." + getDefaultDomain() + "/";
- public static String APP_DIR_UR = "https://www.lanzous.com/b00ngso7e";
+ public static String LAN_ZOU_URL = "https://fycz.lanzoum.com";
+
+ public static String APP_DIR_URL = LAN_ZOU_URL + "/b00ngso7e";
- public static String LAN_ZOUS_URL = "https://fycz.lanzoui.com";
+ public static final String SUB_SOURCE_URL = LAN_ZOU_URL + "/b00pfkkgh";
//字体下载
public static final String FONT_DOWNLOAD_URL = "https://novel." + getDefaultDomain() + "/app/fonts/";
@@ -21,24 +41,25 @@ public class URLCONST {
public static final String YOU_DAO_SEARCH = "http://m.youdao.com/dict?le=eng&q={key}";
-
public static final String FY_READER_URL = "https://fyreader." + getDefaultDomain();
- public static final String AD_URL = FY_READER_URL + "/ad";
- public static final String LOG_UPLOAD_URL = FY_READER_URL + "/logUpload";
- public static final String THANKS_URL = FY_READER_URL + "/thanks/";
public static final String USER_URL = "http://101.43.83.105:12123";
+ public static final String LOG_UPLOAD_URL = USER_URL + "/do/logUpload";
+ public static final String THANKS_URL = USER_URL + "/thanks/";
+ public static final String AD_URL = USER_URL + "/do/ad";
- public static final String DONATE = "https://gitee.com/fengyuecanzhu/Donate/raw/master";
+ public static final String DONATE = "https://fyreader.coding.net/p/img/d/img/git/raw/master/Donate";
- public static final String WX_ZSM = DONATE + "/wx_zsm.png";
+ public static final String WX_ZSM = DONATE + "/wx_zsm.jpg";
public static final String ZFB_SKM = DONATE + "/zfb_skm.jpg";
- public static final String QQ_SKM = DONATE + "/qq_skm.png";
+ public static final String QQ_SKM = DONATE + "/qq_skm.jpg";
public static final String QUOTATION = "https://v1.hitokoto.cn/?encode=json&charset=utf-8";
+ public static final String DEFAULT_PLUGIN_CONFIG_URL = "https://fyreader.coding.net/p/img/d/Plugin/git/raw/master/release/config_FYReader.json";
+
public static String getDefaultDomain() {
- return SharedPreUtils.getInstance().getString("domain", "fycz.tk");
+ return SharedPreUtils.getInstance().getString("domain", "fycz.me");
}
}
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/Date.java b/app/src/main/java/xyz/fycz/myreader/entity/Date.java
index 4d02d06..b92115b 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/Date.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/Date.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/FindKind.java b/app/src/main/java/xyz/fycz/myreader/entity/FindKind.java
index 03b2797..5ec8551 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/FindKind.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/FindKind.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/PluginConfig.kt b/app/src/main/java/xyz/fycz/myreader/entity/PluginConfig.kt
new file mode 100644
index 0000000..f6f18c4
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/PluginConfig.kt
@@ -0,0 +1,35 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity
+
+/**
+ * @author fengyue
+ * @date 2022/3/29 14:55
+ */
+data class PluginConfig(
+ val name: String,
+ val versionCode: Int,
+ val version: String,
+ val url: String,
+ val md5: String,//32位
+ val changelog: String
+) {
+ constructor(name: String, versionCode: Int) :
+ this(name, versionCode, "", "", "", "")
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/Quotation.java b/app/src/main/java/xyz/fycz/myreader/entity/Quotation.java
index 381dba1..ca57c1d 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/Quotation.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/Quotation.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/ReadStyle.java b/app/src/main/java/xyz/fycz/myreader/entity/ReadStyle.java
index b0b19c5..95e690c 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/ReadStyle.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/ReadStyle.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
import com.google.gson.Gson;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/SearchBookBean.java b/app/src/main/java/xyz/fycz/myreader/entity/SearchBookBean.java
index 362c93a..ba39efa 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/SearchBookBean.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/SearchBookBean.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
import java.util.Objects;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/Setting.java b/app/src/main/java/xyz/fycz/myreader/entity/Setting.java
index 682b02b..5f300dc 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/Setting.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/Setting.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
import android.content.Context;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/SharedBook.java b/app/src/main/java/xyz/fycz/myreader/entity/SharedBook.java
index 5e34779..4b2248f 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/SharedBook.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/SharedBook.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
import xyz.fycz.myreader.greendao.entity.Book;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/StrResponse.java b/app/src/main/java/xyz/fycz/myreader/entity/StrResponse.java
index dad38bd..870fa07 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/StrResponse.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/StrResponse.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/Void.java b/app/src/main/java/xyz/fycz/myreader/entity/Void.java
index 02f0c9c..2e74762 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/Void.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/Void.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/WebChapterBean.java b/app/src/main/java/xyz/fycz/myreader/entity/WebChapterBean.java
index f77df56..ff36a2a 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/WebChapterBean.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/WebChapterBean.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity;
import java.util.LinkedHashSet;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/ad/AdBean.kt b/app/src/main/java/xyz/fycz/myreader/entity/ad/AdBean.kt
new file mode 100644
index 0000000..a1ed634
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/ad/AdBean.kt
@@ -0,0 +1,28 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.ad
+
+/**
+ * @author fengyue
+ * @date 2022/3/3 15:00
+ */
+data class AdBean(
+ val status: Int,// 广告展示状态:0:不展示,1:展示信息流广告,2:展示插屏广告
+ val interval: Int,// 广告展示间隔(单位:分钟)
+)
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/ad/AdConfig.java b/app/src/main/java/xyz/fycz/myreader/entity/ad/AdConfig.java
new file mode 100644
index 0000000..24bc986
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/ad/AdConfig.java
@@ -0,0 +1,206 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.ad;
+
+import androidx.annotation.NonNull;
+
+import com.google.gson.Gson;
+
+import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
+
+/**
+ * @author fengyue
+ * @date 2022/2/17 18:56
+ */
+public class AdConfig {
+ //是否云控
+ private boolean isCloud;
+ //是否有广告(总开关)
+ private boolean hasAd;
+ //是否有广告(用户)
+ private boolean userHasAd;
+ //配置过期时间
+ private int expireTime;
+ //应用处于后台一段时间展示开屏广告(单位:分钟)
+ private int backAdTime;
+ //应用回到前台展示广告间隔(单位:分钟)
+ private int intervalAdTime;
+ //单次激励视频可去广告时间(单位:小时),为0时表示关闭去广告
+ private int removeAdTime;
+ //每日最大去除广告次数
+ private int maxRemove;
+ //累计最高去除时间(单位:小时)
+ private int totalRemove;
+ //获取订阅书源是否需要看广告
+ private boolean subSource;
+ //详情页广告配置
+ private AdBean detail;
+ //搜索页广告配置
+ private AdBean search;
+ //阅读页广告配置
+ private AdBean read;
+ //发现页广告配置
+ private AdBean find;
+
+ public AdConfig() {
+ }
+
+ public AdConfig(boolean isCloud, boolean hasAd, boolean userHasAd, int expireTime, int backAdTime, int intervalAdTime, int removeAdTime, int maxRemove, int totalRemove, boolean subSource) {
+ this.isCloud = isCloud;
+ this.hasAd = hasAd;
+ this.userHasAd = userHasAd;
+ this.expireTime = expireTime;
+ this.backAdTime = backAdTime;
+ this.intervalAdTime = intervalAdTime;
+ this.removeAdTime = removeAdTime;
+ this.maxRemove = maxRemove;
+ this.totalRemove = totalRemove;
+ this.subSource = subSource;
+ }
+
+ public boolean isCloud() {
+ return isCloud;
+ }
+
+ public void setCloud(boolean cloud) {
+ isCloud = cloud;
+ }
+
+ public boolean isHasAd() {
+ return hasAd;
+ }
+
+ public void setHasAd(boolean hasAd) {
+ this.hasAd = hasAd;
+ }
+
+ public int getBackAdTime() {
+ return backAdTime;
+ }
+
+ public void setBackAdTime(int backAdTime) {
+ this.backAdTime = backAdTime;
+ }
+
+ public int getIntervalAdTime() {
+ return intervalAdTime;
+ }
+
+ public void setIntervalAdTime(int intervalAdTime) {
+ this.intervalAdTime = intervalAdTime;
+ }
+
+ public int getExpireTime() {
+ return expireTime;
+ }
+
+ public void setExpireTime(int expireTime) {
+ this.expireTime = expireTime;
+ }
+
+ public int getRemoveAdTime() {
+ return removeAdTime;
+ }
+
+ public void setRemoveAdTime(int removeAdTime) {
+ this.removeAdTime = removeAdTime;
+ }
+
+ public int getMaxRemove() {
+ return maxRemove;
+ }
+
+ public void setMaxRemove(int maxRemove) {
+ this.maxRemove = maxRemove;
+ }
+
+ public int getTotalRemove() {
+ return totalRemove;
+ }
+
+ public void setTotalRemove(int totalRemove) {
+ this.totalRemove = totalRemove;
+ }
+
+ public AdBean getDetail() {
+ if (detail == null) {
+ detail = new AdBean(2, 60);
+ }
+ return detail;
+ }
+
+ public void setDetail(AdBean detail) {
+ this.detail = detail;
+ }
+
+ public AdBean getSearch() {
+ if (search == null) {
+ search = new AdBean(0, 60);
+ }
+ return search;
+ }
+
+ public void setSearch(AdBean search) {
+ this.search = search;
+ }
+
+ public AdBean getRead() {
+ if (read == null) {
+ read = new AdBean(0, 60);
+ }
+ return read;
+ }
+
+ public void setRead(AdBean read) {
+ this.read = read;
+ }
+
+ public AdBean getFind() {
+ if (find == null) {
+ find = new AdBean(0, 60);
+ }
+ return find;
+ }
+
+ public void setFind(AdBean find) {
+ this.find = find;
+ }
+
+ public boolean isSubSource() {
+ return subSource;
+ }
+
+ public void setSubSource(boolean subSource) {
+ this.subSource = subSource;
+ }
+
+ public boolean isUserHasAd() {
+ return userHasAd;
+ }
+
+ public void setUserHasAd(boolean userHasAd) {
+ this.userHasAd = userHasAd;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return GsonExtensionsKt.getGSON().toJson(this);
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/BookType.java b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/BookType.java
index 98d1d5a..58086a1 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/BookType.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/BookType.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.bookstore;
public class BookType {
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/FindBook.java b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/FindBook.java
index 6689689..1ce5683 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/FindBook.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/FindBook.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.bookstore;
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/QDBook.java b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/QDBook.java
index 0191092..6da939b 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/QDBook.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/QDBook.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.bookstore;
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/RankBook.java b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/RankBook.java
index 8c11102..85eb169 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/RankBook.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/RankBook.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.bookstore;
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/SortBook.java b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/SortBook.java
index c2d7929..0a1d654 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/bookstore/SortBook.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/bookstore/SortBook.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.bookstore;
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/lanzou/LanZouFile.kt b/app/src/main/java/xyz/fycz/myreader/entity/lanzou/LanZouFile.kt
new file mode 100644
index 0000000..7ea5192
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/lanzou/LanZouFile.kt
@@ -0,0 +1,30 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.lanzou
+
+/**
+ * @author fengyue
+ * @date 2022/3/3 8:53
+ */
+data class LanZouFile(
+ var id: String,
+ var name_all: String,
+ var size: String,
+ var time: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/lanzou/LanZouParseBean.kt b/app/src/main/java/xyz/fycz/myreader/entity/lanzou/LanZouParseBean.kt
new file mode 100644
index 0000000..19cad8a
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/lanzou/LanZouParseBean.kt
@@ -0,0 +1,30 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.lanzou
+
+/**
+ * @author fengyue
+ * @date 2022/1/22 20:15
+ */
+data class LanZouParseBean(
+ var zt: Int,
+ var dom: String,
+ var url: String,
+ var inf: String
+)
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugBook.kt b/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugBook.kt
index 5401848..f8c897c 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugBook.kt
+++ b/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugBook.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.sourcedebug
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugChapter.kt b/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugChapter.kt
index 2469363..27c467b 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugChapter.kt
+++ b/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugChapter.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.sourcedebug
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugEntity.java b/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugEntity.java
index 305de02..85b8026 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugEntity.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/DebugEntity.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.sourcedebug;
import android.os.Parcel;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/ListResult.kt b/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/ListResult.kt
index ff302c9..60c38ae 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/ListResult.kt
+++ b/app/src/main/java/xyz/fycz/myreader/entity/sourcedebug/ListResult.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.sourcedebug
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntity.kt b/app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntity.kt
index a1d612a..7d4b505 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntity.kt
+++ b/app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntity.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.sourceedit
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntityUtil.kt b/app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntityUtil.kt
index 14b60b3..89be965 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntityUtil.kt
+++ b/app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntityUtil.kt
@@ -1,8 +1,25 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.sourceedit
import xyz.fycz.myreader.R
import xyz.fycz.myreader.greendao.entity.rule.*
-import java.util.*
import kotlin.collections.ArrayList
/**
@@ -34,6 +51,7 @@ object EditEntityUtil {
)
add(EditEntity("loginUrl", source?.loginUrl, R.string.login_url, ""))
add(EditEntity("sourceComment", source?.sourceComment, R.string.comment, "这是您留给使用者的说明"))
+ add(EditEntity("concurrentRate", source?.concurrentRate, R.string.source_concurrent_rate, ""))
}
return sourceEntities
}
@@ -84,7 +102,7 @@ object EditEntityUtil {
add(EditEntity("url", findRule?.url, R.string.r_find_url))
add(
EditEntity(
- "bookList", findRule?.bookList, R.string.r_book_list,
+ "bookList", findRule?.list, R.string.r_book_list,
"对于Matcher解析器:此处填写书籍列表所在区间,仅支持普通函数;" +
"\n对于Xpath/JsonPath解析器:此处填写书籍列表规则,仅支持列表函数"
)
@@ -153,6 +171,18 @@ object EditEntityUtil {
"对于Xpath/JsonPath解析器:此处填写章节URL规则"
)
)
+ add(
+ EditEntity(
+ "isVip", tocRule?.isVip, R.string.rule_is_vip,
+ ""
+ )
+ )
+ add(
+ EditEntity(
+ "updateTime", tocRule?.updateTime, R.string.rule_update_time,
+ ""
+ )
+ )
add(
EditEntity(
"tocUrlNext", tocRule?.tocUrlNext, R.string.rule_next_toc_url,
@@ -179,6 +209,24 @@ object EditEntityUtil {
"填写后正文时将会不断地从下一页获取内容,直至下一页URL为空时停止,注意:千万不要获取恒存在的URL,否则将出现死循环甚至崩溃"
)
)
+ add(
+ EditEntity(
+ "webJs", contentRule?.webJs, R.string.rule_web_js,
+ ""
+ )
+ )
+ add(
+ EditEntity(
+ "sourceRegex", contentRule?.sourceRegex, R.string.rule_source_regex,
+ ""
+ )
+ )
+ add(
+ EditEntity(
+ "replaceRegex", contentRule?.replaceRegex, R.string.rule_replace_regex,
+ ""
+ )
+ )
}
return contentEntities
}
@@ -195,6 +243,7 @@ object EditEntityUtil {
"sourceHeaders" -> source.sourceHeaders = it.value
"loginUrl" -> source.loginUrl = it.value
"sourceComment" -> source.sourceComment = it.value
+ "concurrentRate" -> source.concurrentRate = it.value
}
}
return source
@@ -229,7 +278,7 @@ object EditEntityUtil {
findEntities.forEach {
when (it.key) {
"url" -> findRule.url = it.value
- "bookList" -> findRule.bookList = it.value
+ "bookList" -> findRule.list = it.value
"name" -> findRule.name = it.value
"author" -> findRule.author = it.value
"type" -> findRule.type = it.value
@@ -275,6 +324,8 @@ object EditEntityUtil {
"chapterBaseUrl" -> tocRule.chapterBaseUrl = it.value
"chapterName" -> tocRule.chapterName = it.value
"chapterUrl" -> tocRule.chapterUrl = it.value
+ "isVip" -> tocRule.isVip = it.value
+ "updateTime" -> tocRule.updateTime = it.value
"tocUrlNext" -> tocRule.tocUrlNext = it.value
}
}
@@ -288,6 +339,9 @@ object EditEntityUtil {
"content" -> contentRule.content = it.value
"contentBaseUrl" -> contentRule.contentBaseUrl = it.value
"contentUrlNext" -> contentRule.contentUrlNext = it.value
+ "webJs" -> contentRule.webJs = it.value
+ "sourceRegex" -> contentRule.sourceRegex = it.value
+ "replaceRegex" -> contentRule.replaceRegex = it.value
}
}
return contentRule
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSource3Bean.java b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSource3Bean.java
index cf34cb1..851630f 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSource3Bean.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSource3Bean.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.thirdsource;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSourceBean.java b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSourceBean.java
index 9d2ef39..5ec8530 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSourceBean.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/BookSourceBean.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.thirdsource;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ThirdSourceUtil.java b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ThirdSourceUtil.java
index 26ce800..9df1930 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ThirdSourceUtil.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ThirdSourceUtil.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.entity.thirdsource;
import java.util.ArrayList;
@@ -67,7 +85,7 @@ public class ThirdSourceUtil {
FindRule findRule = new FindRule();
findRule.setUrl(bean.getRuleFindUrl());
- findRule.setBookList(bean.getRuleFindList());
+ findRule.setList(bean.getRuleFindList());
findRule.setName(bean.getRuleFindName());
findRule.setAuthor(bean.getRuleFindAuthor());
findRule.setType(bean.getRuleFindKind());
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/BookInfoRule3.kt b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/BookInfoRule3.kt
new file mode 100644
index 0000000..7118334
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/BookInfoRule3.kt
@@ -0,0 +1,37 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.thirdsource.source3
+
+/**
+ * @author fengyue
+ * @date 2022/1/20 13:49
+ */
+data class BookInfoRule3(
+ var init: String? = null,
+ var name: String? = null,
+ var author: String? = null,
+ var intro: String? = null,
+ var kind: String? = null,
+ var lastChapter: String? = null,
+ var updateTime: String? = null,
+ var coverUrl: String? = null,
+ var tocUrl: String? = null,
+ var wordCount: String? = null,
+ var canReName: String? = null
+)
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ContentRule3.kt b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ContentRule3.kt
new file mode 100644
index 0000000..4693f7e
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ContentRule3.kt
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.thirdsource.source3
+
+/**
+ * @author fengyue
+ * @date 2022/1/20 13:50
+ */
+data class ContentRule3(
+ var content: String? = null,
+ var nextContentUrl: String? = null,
+ var webJs: String? = null,
+ var sourceRegex: String? = null,
+ var replaceRegex: String? = null, //替换规则
+ var imageStyle: String? = null, //默认大小居中,FULL最大宽度
+ var payAction: String? = null, //购买操作,url/js
+)
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ExploreKind.kt b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ExploreKind3.kt
similarity index 50%
rename from app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ExploreKind.kt
rename to app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ExploreKind3.kt
index 3ce4dc5..05bd7ae 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/ExploreKind.kt
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ExploreKind3.kt
@@ -1,6 +1,24 @@
-package xyz.fycz.myreader.entity.thirdsource
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
-data class ExploreKind(
+package xyz.fycz.myreader.entity.thirdsource.source3
+
+data class ExploreKind3(
val title: String,
val url: String? = null,
val style: Style? = null
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ExploreRule3.kt b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ExploreRule3.kt
new file mode 100644
index 0000000..0804ee4
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/ExploreRule3.kt
@@ -0,0 +1,36 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.thirdsource.source3
+
+/**
+ * @author fengyue
+ * @date 2022/1/20 13:50
+ */
+data class ExploreRule3(
+ var bookList: String? = null,
+ var name: String? = null,
+ var author: String? = null,
+ var intro: String? = null,
+ var kind: String? = null,
+ var lastChapter: String? = null,
+ var updateTime: String? = null,
+ var bookUrl: String? = null,
+ var coverUrl: String? = null,
+ var wordCount: String? = null
+)
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/SearchRule3.kt b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/SearchRule3.kt
new file mode 100644
index 0000000..af5da54
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/SearchRule3.kt
@@ -0,0 +1,37 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.thirdsource.source3
+
+/**
+ * @author fengyue
+ * @date 2022/1/20 13:48
+ */
+data class SearchRule3(
+ var checkKeyWord: String? = null, // 校验关键字
+ var bookList: String? = null,
+ var name: String? = null,
+ var author: String? = null,
+ var intro: String? = null,
+ var kind: String? = null,
+ var lastChapter: String? = null,
+ var updateTime: String? = null,
+ var bookUrl: String? = null,
+ var coverUrl: String? = null,
+ var wordCount: String? = null
+)
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/Source3.kt b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/Source3.kt
new file mode 100644
index 0000000..4bb45e5
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/Source3.kt
@@ -0,0 +1,54 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.thirdsource.source3
+
+/**
+ * @author fengyue
+ * @date 2022/1/20 13:47
+ */
+data class Source3(
+ var bookSourceUrl: String = "", // 地址,包括 http/https
+ var bookSourceName: String = "", // 名称
+ var bookSourceGroup: String? = null, // 分组
+ //未加
+ var bookSourceType: Int = 0, // 类型,0 文本,1 音频, 3 图片
+ var bookUrlPattern: String? = null, // 详情页url正则
+ var customOrder: Int = 0, // 手动排序编号
+ var enabled: Boolean = true, // 是否启用
+ //未加
+ var enabledExplore: Boolean = true, // 启用发现
+ var concurrentRate: String? = null, // 并发率
+ var header: String? = null, // 请求头
+ var loginUrl: String? = null, // 登录地址
+ //未加
+ var loginUi: String? = null, // 登录UI
+ var loginCheckJs: String? = null, // 登录检测js
+ var bookSourceComment: String? = null, // 注释
+ var lastUpdateTime: Long = 0, // 最后更新时间,用于排序
+ //未加
+ var respondTime: Long = 180000L, // 响应时间,用于排序
+ var weight: Int = 0, // 智能排序的权重
+ var exploreUrl: String? = null, // 发现url
+ var ruleExplore: ExploreRule3? = null, // 发现规则
+ var searchUrl: String? = null, // 搜索url
+ var ruleSearch: SearchRule3? = null, // 搜索规则
+ var ruleBookInfo: BookInfoRule3? = null, // 书籍信息页规则
+ var ruleToc: TocRule3? = null, // 目录页规则
+ var ruleContent: ContentRule3? = null // 正文页规则
+)
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/Third3SourceUtil.kt b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/Third3SourceUtil.kt
new file mode 100644
index 0000000..395a6ef
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/Third3SourceUtil.kt
@@ -0,0 +1,119 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.thirdsource.source3
+
+import xyz.fycz.myreader.common.APPCONST
+import xyz.fycz.myreader.greendao.entity.rule.*
+
+/**
+ * @author fengyue
+ * @date 2022/1/20 13:51
+ */
+object Third3SourceUtil {
+ fun source3ToSource(bean: Source3): BookSource {
+ val bookSource = BookSource()
+ bookSource.sourceUrl = bean.bookSourceUrl
+ bookSource.sourceName = bean.bookSourceName
+ bookSource.sourceGroup = bean.bookSourceGroup
+ bookSource.sourceType = APPCONST.THIRD_3_SOURCE
+ bookSource.orderNum = bean.customOrder
+ bookSource.enable = bean.enabled
+ bookSource.concurrentRate = bean.concurrentRate
+ bookSource.sourceHeaders = bean.header
+ bookSource.loginUrl = bean.loginUrl
+ bookSource.loginCheckJs = bean.loginCheckJs
+ bookSource.sourceComment = bean.bookSourceComment
+ bookSource.lastUpdateTime = bean.lastUpdateTime
+ bookSource.weight = bean.weight
+
+
+ val searchRule = SearchRule()
+ val ruleSearch = bean.ruleSearch
+ searchRule.searchUrl = bean.searchUrl
+ searchRule.list = ruleSearch?.bookList
+ searchRule.name = ruleSearch?.name
+ searchRule.author = ruleSearch?.author
+ searchRule.desc = ruleSearch?.intro
+ searchRule.type = ruleSearch?.kind
+ searchRule.lastChapter = ruleSearch?.lastChapter
+ searchRule.updateTime = ruleSearch?.updateTime
+ searchRule.infoUrl = ruleSearch?.bookUrl
+ searchRule.imgUrl = ruleSearch?.coverUrl
+ searchRule.wordCount = ruleSearch?.wordCount
+ searchRule.isRelatedWithInfo = true
+ bookSource.searchRule = searchRule
+
+ val infoRule = InfoRule()
+ val ruleInfo = bean.ruleBookInfo
+ infoRule.urlPattern = bean.bookUrlPattern
+ infoRule.init = ruleInfo?.init
+ infoRule.name = ruleInfo?.name
+ infoRule.author = ruleInfo?.author
+ infoRule.desc = ruleInfo?.intro
+ infoRule.type = ruleInfo?.kind
+ infoRule.lastChapter = ruleInfo?.lastChapter
+ infoRule.updateTime = ruleInfo?.updateTime
+ infoRule.imgUrl = ruleInfo?.coverUrl
+ infoRule.tocUrl = ruleInfo?.tocUrl
+ infoRule.wordCount = ruleInfo?.wordCount
+ bookSource.infoRule = infoRule
+
+ val tocRule = TocRule()
+ val ruleToc = bean.ruleToc
+ tocRule.chapterList = ruleToc?.chapterList
+ tocRule.chapterName = ruleToc?.chapterName
+ tocRule.chapterUrl = ruleToc?.chapterUrl
+ tocRule.isVip = ruleToc?.isVip
+ tocRule.isPay = ruleToc?.isPay
+ tocRule.updateTime = ruleToc?.updateTime
+ tocRule.tocUrlNext = ruleToc?.nextTocUrl
+ bookSource.tocRule = tocRule
+
+ val contentRule = ContentRule()
+ val ruleContent = bean.ruleContent
+ contentRule.content = ruleContent?.content
+ contentRule.contentUrlNext = ruleContent?.nextContentUrl
+ contentRule.replaceRegex = ruleContent?.replaceRegex
+ bookSource.contentRule = contentRule
+
+ val findRule = FindRule()
+ val ruleFind = bean.ruleExplore
+ findRule.url = bean.exploreUrl
+ findRule.list = ruleFind?.bookList
+ findRule.name = ruleFind?.name
+ findRule.author = ruleFind?.author
+ findRule.desc = ruleFind?.intro
+ findRule.type = ruleFind?.kind
+ findRule.lastChapter = ruleFind?.lastChapter
+ findRule.updateTime = ruleFind?.updateTime
+ findRule.imgUrl = ruleFind?.coverUrl
+ findRule.infoUrl = ruleFind?.bookUrl
+ findRule.wordCount = ruleFind?.wordCount
+ bookSource.findRule = findRule
+ return bookSource
+ }
+
+ fun source3sToSources(source3s: List): List {
+ val sources = mutableListOf()
+ source3s.forEach {
+ sources.add(source3ToSource(it))
+ }
+ return sources
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/TocRule3.kt b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/TocRule3.kt
new file mode 100644
index 0000000..6bd1654
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/thirdsource/source3/TocRule3.kt
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.entity.thirdsource.source3
+
+/**
+ * @author fengyue
+ * @date 2022/1/20 13:50
+ */
+data class TocRule3(
+ var chapterList: String? = null,
+ var chapterName: String? = null,
+ var chapterUrl: String? = null,
+ var isVip: String? = null,
+ var isPay: String? = null,
+ var updateTime: String? = null,
+ var nextTocUrl: String? = null
+)
diff --git a/app/src/main/java/xyz/fycz/myreader/enums/BookcaseStyle.java b/app/src/main/java/xyz/fycz/myreader/enums/BookcaseStyle.java
index 1412b6d..337d4c9 100644
--- a/app/src/main/java/xyz/fycz/myreader/enums/BookcaseStyle.java
+++ b/app/src/main/java/xyz/fycz/myreader/enums/BookcaseStyle.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.enums;
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/enums/Font.java b/app/src/main/java/xyz/fycz/myreader/enums/Font.java
index f9a18f9..77d6598 100644
--- a/app/src/main/java/xyz/fycz/myreader/enums/Font.java
+++ b/app/src/main/java/xyz/fycz/myreader/enums/Font.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.enums;
import xyz.fycz.myreader.common.URLCONST;
@@ -6,28 +24,28 @@ public enum Font {
默认字体( "默认字体"),
本地字体( "默认字体"),
- 方正楷体( URLCONST.LAN_ZOUS_URL + "/ilLFMe6kefe"),
- 方正行楷( URLCONST.LAN_ZOUS_URL + "/imFvne6keji"),
- 经典宋体(URLCONST.LAN_ZOUS_URL + "/idhI5e6keqf"),
- 方正硬笔行书(URLCONST.LAN_ZOUS_URL + "/ilVh6ep9xja"),
- 包图小白体(URLCONST.LAN_ZOUS_URL + "/i5qgAicrirc"),
- 仓耳非白W02(URLCONST.LAN_ZOUS_URL + "/iHwRnicriuf"),
- 仓耳舒圆体W02(URLCONST.LAN_ZOUS_URL + "/i3GVPicrj3e"),
- 仓耳与墨W02(URLCONST.LAN_ZOUS_URL + "/ivhv9icrj7i"),
- 方正仿宋简体(URLCONST.LAN_ZOUS_URL + "/iEcCHicrjef"),
- 方正黑体简体(URLCONST.LAN_ZOUS_URL + "/iw8kKicrjij"),
- 方正书宋简体(URLCONST.LAN_ZOUS_URL + "/i5976icrjmd"),
- 品如手写体(URLCONST.LAN_ZOUS_URL + "/iZccuicrjyf"),
- 千图小兔体(URLCONST.LAN_ZOUS_URL + "/iOONMicrkda"),
- 手书体(URLCONST.LAN_ZOUS_URL + "/iqbmdicrkvi"),
- 演示春风楷(URLCONST.LAN_ZOUS_URL + "/ioRJSicrldg"),
- 演示秋鸿楷(URLCONST.LAN_ZOUS_URL + "/i8qnzicrlsb"),
- 演示夏行楷(URLCONST.LAN_ZOUS_URL + "/iyYUTicrm6f"),
- 演示悠然小楷(URLCONST.LAN_ZOUS_URL + "/ikKq7icrmrg"),
- 杨任东竹石体(URLCONST.LAN_ZOUS_URL + "/iiWdVicrnbg"),
- 站酷仓耳渔阳体(URLCONST.LAN_ZOUS_URL + "/if5weicrnje"),
- 迷你隶书( URLCONST.LAN_ZOUS_URL + "/ihaXVe6kekj"),
- 方正黄草(URLCONST.LAN_ZOUS_URL + "/iQg67e6keed");
+ 方正楷体( URLCONST.LAN_ZOU_URL + "/ilLFMe6kefe"),
+ 方正行楷( URLCONST.LAN_ZOU_URL + "/imFvne6keji"),
+ 经典宋体(URLCONST.LAN_ZOU_URL + "/idhI5e6keqf"),
+ 方正硬笔行书(URLCONST.LAN_ZOU_URL + "/ilVh6ep9xja"),
+ 包图小白体(URLCONST.LAN_ZOU_URL + "/i5qgAicrirc"),
+ 仓耳非白W02(URLCONST.LAN_ZOU_URL + "/iHwRnicriuf"),
+ 仓耳舒圆体W02(URLCONST.LAN_ZOU_URL + "/i3GVPicrj3e"),
+ 仓耳与墨W02(URLCONST.LAN_ZOU_URL + "/ivhv9icrj7i"),
+ 方正仿宋简体(URLCONST.LAN_ZOU_URL + "/iEcCHicrjef"),
+ 方正黑体简体(URLCONST.LAN_ZOU_URL + "/iw8kKicrjij"),
+ 方正书宋简体(URLCONST.LAN_ZOU_URL + "/i5976icrjmd"),
+ 品如手写体(URLCONST.LAN_ZOU_URL + "/iZccuicrjyf"),
+ 千图小兔体(URLCONST.LAN_ZOU_URL + "/iOONMicrkda"),
+ 手书体(URLCONST.LAN_ZOU_URL + "/iqbmdicrkvi"),
+ 演示春风楷(URLCONST.LAN_ZOU_URL + "/ioRJSicrldg"),
+ 演示秋鸿楷(URLCONST.LAN_ZOU_URL + "/i8qnzicrlsb"),
+ 演示夏行楷(URLCONST.LAN_ZOU_URL + "/iyYUTicrm6f"),
+ 演示悠然小楷(URLCONST.LAN_ZOU_URL + "/ikKq7icrmrg"),
+ 杨任东竹石体(URLCONST.LAN_ZOU_URL + "/iiWdVicrnbg"),
+ 站酷仓耳渔阳体(URLCONST.LAN_ZOU_URL + "/if5weicrnje"),
+ 迷你隶书( URLCONST.LAN_ZOU_URL + "/ihaXVe6kekj"),
+ 方正黄草(URLCONST.LAN_ZOU_URL + "/iQg67e6keed");
public String downloadPath;
diff --git a/app/src/main/java/xyz/fycz/myreader/enums/Language.java b/app/src/main/java/xyz/fycz/myreader/enums/Language.java
index 4943bc9..e1f16c3 100644
--- a/app/src/main/java/xyz/fycz/myreader/enums/Language.java
+++ b/app/src/main/java/xyz/fycz/myreader/enums/Language.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.enums;
public enum Language {
diff --git a/app/src/main/java/xyz/fycz/myreader/enums/LocalBookSource.java b/app/src/main/java/xyz/fycz/myreader/enums/LocalBookSource.java
index b1ccf5e..7763e7c 100644
--- a/app/src/main/java/xyz/fycz/myreader/enums/LocalBookSource.java
+++ b/app/src/main/java/xyz/fycz/myreader/enums/LocalBookSource.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.enums;
import xyz.fycz.myreader.R;
diff --git a/app/src/main/java/xyz/fycz/myreader/experiment/BookWCEstimate.kt b/app/src/main/java/xyz/fycz/myreader/experiment/BookWCEstimate.kt
index 8a644b7..4fb4a9e 100644
--- a/app/src/main/java/xyz/fycz/myreader/experiment/BookWCEstimate.kt
+++ b/app/src/main/java/xyz/fycz/myreader/experiment/BookWCEstimate.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.experiment
import xyz.fycz.myreader.common.APPCONST
@@ -49,13 +67,13 @@ class BookWCEstimate {
var cachedChapterSize = 0
for (chapter in chapters) {
if (cachedChapterSize >= 20) break
- if (ChapterService.isChapterCached(chapter.bookId, chapter.title)) {
+ if (ChapterService.isChapterCached(chapter)) {
cachedChapterSize++
}
}
- if (cachedChapterSize < 20 && chapters.size > 50) return -2
+ if ((cachedChapterSize < 20 && chapters.size > 50) || cachedChapterSize == 0) return -2
chapters.forEach { chapter ->
- if (ChapterService.isChapterCached(chapter.bookId, chapter.title)) {
+ if (ChapterService.isChapterCached(chapter)) {
sum += countChar(
File(
APPCONST.BOOK_CACHE_PATH + chapter.bookId
diff --git a/app/src/main/java/xyz/fycz/myreader/experiment/DoubleUtils.java b/app/src/main/java/xyz/fycz/myreader/experiment/DoubleUtils.java
index 119e4e6..cf3366d 100644
--- a/app/src/main/java/xyz/fycz/myreader/experiment/DoubleUtils.java
+++ b/app/src/main/java/xyz/fycz/myreader/experiment/DoubleUtils.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.experiment;
import java.math.BigDecimal;
diff --git a/app/src/main/java/xyz/fycz/myreader/experiment/LinearRegression.java b/app/src/main/java/xyz/fycz/myreader/experiment/LinearRegression.java
index cf7d09e..3869031 100644
--- a/app/src/main/java/xyz/fycz/myreader/experiment/LinearRegression.java
+++ b/app/src/main/java/xyz/fycz/myreader/experiment/LinearRegression.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.experiment;
import static xyz.fycz.myreader.experiment.DoubleUtils.add;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/DbManager.java b/app/src/main/java/xyz/fycz/myreader/greendao/DbManager.java
index 7f2c0e0..d57c917 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/DbManager.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/DbManager.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/convert/ContentRuleConvert.java b/app/src/main/java/xyz/fycz/myreader/greendao/convert/ContentRuleConvert.java
index 0f136f2..3166447 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/convert/ContentRuleConvert.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/convert/ContentRuleConvert.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.convert;
import org.greenrobot.greendao.converter.PropertyConverter;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/convert/FindRuleConvert.java b/app/src/main/java/xyz/fycz/myreader/greendao/convert/FindRuleConvert.java
index 0b429c5..73e65be 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/convert/FindRuleConvert.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/convert/FindRuleConvert.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.convert;
import org.greenrobot.greendao.converter.PropertyConverter;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/convert/InfoRuleConvert.java b/app/src/main/java/xyz/fycz/myreader/greendao/convert/InfoRuleConvert.java
index aef7016..d64ec31 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/convert/InfoRuleConvert.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/convert/InfoRuleConvert.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.convert;
import org.greenrobot.greendao.converter.PropertyConverter;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/convert/SearchRuleConvert.java b/app/src/main/java/xyz/fycz/myreader/greendao/convert/SearchRuleConvert.java
index f4f8751..b6a88a6 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/convert/SearchRuleConvert.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/convert/SearchRuleConvert.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.convert;
import org.greenrobot.greendao.converter.PropertyConverter;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/convert/SearchWord1Convert.kt b/app/src/main/java/xyz/fycz/myreader/greendao/convert/SearchWord1Convert.kt
index 5e0f933..6e25a49 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/convert/SearchWord1Convert.kt
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/convert/SearchWord1Convert.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.convert
import org.greenrobot.greendao.converter.PropertyConverter
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/convert/TocRuleConvert.java b/app/src/main/java/xyz/fycz/myreader/greendao/convert/TocRuleConvert.java
index d458d89..380c6b8 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/convert/TocRuleConvert.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/convert/TocRuleConvert.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.convert;
import org.greenrobot.greendao.converter.PropertyConverter;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java
index 54cd9fc..5a3d123 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java
@@ -1,8 +1,28 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity;
import android.text.TextUtils;
+import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
@@ -13,7 +33,10 @@ import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Transient;
import xyz.fycz.myreader.greendao.service.BookService;
+import xyz.fycz.myreader.model.third3.analyzeRule.RuleDataInterface;
import xyz.fycz.myreader.util.SharedPreUtils;
+import xyz.fycz.myreader.util.help.StringHelper;
+import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
import java.io.Serializable;
import java.util.HashMap;
@@ -23,7 +46,7 @@ import java.util.Objects;
import static xyz.fycz.myreader.common.APPCONST.MAP_STRING;
@Entity
-public class Book implements Serializable {
+public class Book implements Serializable, RuleDataInterface {
@Transient
private static final long serialVersionUID = 1L;
@@ -87,11 +110,11 @@ public class Book implements Serializable {
@Generated(hash = 1472063028)
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 newestChapterId,
- String newestChapterTitle, String historyChapterId, int histtoryChapterNum, int sortCode, int noReadNum,
- int chapterTotalNum, int lastReadPosition, String source, boolean isCloseUpdate, boolean isDownLoadAll,
- String groupId, int groupSort, boolean reSeg, String tag, Boolean replaceEnable, long lastReadTime,
- String variable) {
+ String type, String updateDate, String wordCount, String status, String newestChapterId,
+ String newestChapterTitle, String historyChapterId, int histtoryChapterNum, int sortCode, int noReadNum,
+ int chapterTotalNum, int lastReadPosition, String source, boolean isCloseUpdate, boolean isDownLoadAll,
+ String groupId, int groupSort, boolean reSeg, String tag, Boolean replaceEnable, long lastReadTime,
+ String variable) {
this.id = id;
this.name = name;
this.chapterUrl = chapterUrl;
@@ -301,8 +324,11 @@ public class Book implements Serializable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
+ boolean flag = chapterUrl == null ?
+ (infoUrl == null || infoUrl.equals(book.infoUrl)) :
+ chapterUrl.equals(book.chapterUrl);
return name.equals(book.name) &&
- chapterUrl.equals(book.chapterUrl) &&
+ flag && author != null &&
author.equals(book.author) &&
source.equals(book.source);
}
@@ -378,31 +404,42 @@ public class Book implements Serializable {
this.status = status;
}
- public void putVariable(String key, String value) {
+ public void putVariable(@NonNull String key, String value) {
if (variableMap == null) {
variableMap = new HashMap<>();
}
variableMap.put(key, value);
- variable = new Gson().toJson(variableMap);
+ variable = GsonExtensionsKt.getGSON().toJson(variableMap);
}
+ @NonNull
public Map getVariableMap() {
if (variableMap == null && !TextUtils.isEmpty(variable)) {
- variableMap = new Gson().fromJson(variable, MAP_STRING);
+ variableMap = GsonExtensionsKt.getGSON().fromJson(variable, MAP_STRING);
+ }
+ if (variableMap == null) {
+ variableMap = new HashMap<>();
}
return variableMap;
}
+ public void setVariableMap(Map variableMap) {
+ this.variableMap = variableMap;
+ }
+
public String getVariable() {
return this.variable;
}
-
public void setVariable(String variable) {
this.variable = variable;
}
+ public Map getCatheMap() {
+ return catheMap;
+ }
+
public void putCathe(String key, String value) {
if (catheMap == null) {
catheMap = new HashMap<>();
@@ -410,14 +447,18 @@ public class Book implements Serializable {
catheMap.put(key, value);
}
- public String getCathe(String key){
- if (catheMap == null){
+ public String getCathe(String key) {
+ if (catheMap == null) {
return "";
}
return catheMap.get(key);
}
- public void clearCathe(){
+ public void setCatheMap(Map catheMap) {
+ this.catheMap = catheMap;
+ }
+
+ public void clearCathe() {
if (catheMap != null) {
catheMap.clear();
}
@@ -430,4 +471,46 @@ public class Book implements Serializable {
public void setReSeg(boolean reSeg) {
this.reSeg = reSeg;
}
+
+ @Nullable
+ @Override
+ public String getVariable(@NonNull String key) {
+ return getVariableMap().get(key);
+ }
+
+ public Book changeSource(Book newBook) {
+ Book bookTem = (Book) clone();
+ bookTem.clearCathe();
+ bookTem.setChapterUrl(newBook.getChapterUrl());
+ bookTem.setInfoUrl(newBook.getInfoUrl());
+ bookTem.setSource(newBook.getSource());
+ if (!StringHelper.isEmpty(newBook.getImgUrl())) {
+ bookTem.setImgUrl(newBook.getImgUrl());
+ }
+ if (!StringHelper.isEmpty(newBook.getType())) {
+ bookTem.setType(newBook.getType());
+ }
+ if (!StringHelper.isEmpty(newBook.getDesc())) {
+ bookTem.setDesc(newBook.getDesc());
+ }
+ if (!StringHelper.isEmpty(newBook.getUpdateDate())) {
+ bookTem.setUpdateDate(newBook.getUpdateDate());
+ }
+ if (!StringHelper.isEmpty(newBook.getWordCount())) {
+ bookTem.setWordCount(newBook.getWordCount());
+ }
+ if (!StringHelper.isEmpty(newBook.getStatus())) {
+ bookTem.setStatus(newBook.getStatus());
+ }
+ if (!StringHelper.isEmpty(newBook.getVariable())) {
+ bookTem.setVariable(newBook.getVariable());
+ bookTem.setVariableMap(newBook.getVariableMap());
+ }
+ if (newBook.getCatheMap() != null) {
+ bookTem.setCatheMap(newBook.getCatheMap());
+ }
+ return bookTem;
+ }
+
+ public void setReverseToc(boolean reverseToc){}
}
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookGroup.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookGroup.java
index fd1c6fc..67e1925 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookGroup.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookGroup.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity;
import org.greenrobot.greendao.annotation.Entity;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookMark.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookMark.java
index 58afb76..324e870 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookMark.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/BookMark.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity;
import org.greenrobot.greendao.annotation.*;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Cache.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Cache.java
new file mode 100644
index 0000000..b0d35d0
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Cache.java
@@ -0,0 +1,72 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.greendao.entity;
+
+import org.greenrobot.greendao.annotation.Entity;
+import org.greenrobot.greendao.annotation.Id;
+import org.greenrobot.greendao.annotation.Generated;
+
+/**
+ * @author fengyue
+ * @date 2022/1/18 10:20
+ */
+@Entity
+public class Cache {
+ @Id
+ private String key;
+
+ private String value;
+
+ private long deadLine;
+
+ @Generated(hash = 1252535078)
+ public Cache(String key, String value, long deadLine) {
+ this.key = key;
+ this.value = value;
+ this.deadLine = deadLine;
+ }
+
+ @Generated(hash = 1305017356)
+ public Cache() {
+ }
+
+ public String getKey() {
+ return this.key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public long getDeadLine() {
+ return this.deadLine;
+ }
+
+ public void setDeadLine(long deadLine) {
+ this.deadLine = deadLine;
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Chapter.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Chapter.java
index 4136ce9..b2d37ea 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/Chapter.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/Chapter.java
@@ -1,22 +1,51 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity;
+import static xyz.fycz.myreader.common.APPCONST.MAP_STRING;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+
+import com.google.gson.Gson;
+
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
+import org.greenrobot.greendao.annotation.Transient;
+
import xyz.fycz.myreader.common.APPCONST;
+import xyz.fycz.myreader.greendao.service.ChapterService;
+import xyz.fycz.myreader.model.third3.analyzeRule.RuleDataInterface;
import xyz.fycz.myreader.util.utils.FileUtils;
+import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
import java.io.File;
-
-/**
- * 章节
- * Created by zhao on 2017/7/24.
- */
+import java.util.HashMap;
+import java.util.Map;
@Entity
-public class Chapter {
+public class Chapter implements RuleDataInterface {
@Id
private String id;
@@ -24,6 +53,9 @@ public class Chapter {
private int number;//章节序号
private String title;//章节标题
private String url;//章节链接(本地书籍为:字符编码)
+ private boolean isVip;//是否VIP
+ private boolean isPay;//是否已购买
+ private String updateTime;//更新时间
@Nullable
private String content;//章节正文
@@ -32,64 +64,85 @@ public class Chapter {
//章节内容在文章中的终止位置(本地)
private long end;
+ private String variable;
+ @Transient
+ private Map variableMap;
+
- @Generated(hash = 763230955)
+ @Generated(hash = 1109296579)
public Chapter(String id, String bookId, int number, String title, String url,
- String content, long start, long end) {
+ boolean isVip, boolean isPay, String updateTime, String content,
+ long start, long end, String variable) {
this.id = id;
this.bookId = bookId;
this.number = number;
this.title = title;
this.url = url;
+ this.isVip = isVip;
+ this.isPay = isPay;
+ this.updateTime = updateTime;
this.content = content;
this.start = start;
this.end = end;
+ this.variable = variable;
}
+
@Generated(hash = 393170288)
public Chapter() {
}
+
+
public String getId() {
return this.id;
}
+
public void setId(String id) {
this.id = id;
}
+
public String getBookId() {
return this.bookId;
}
+
public void setBookId(String bookId) {
this.bookId = bookId;
}
+
public int getNumber() {
return this.number;
}
+
public void setNumber(int number) {
this.number = number;
}
+
public String getTitle() {
return this.title;
}
+
public void setTitle(String title) {
this.title = title;
}
+
public String getUrl() {
return this.url;
}
+
public void setUrl(String url) {
this.url = url;
}
+
public String getContent() {
if (end > 0) return end + "";
- String filePath = APPCONST.BOOK_CACHE_PATH + bookId
- + File.separator + title + FileUtils.SUFFIX_FY;
- File file = new File(filePath);
- if (file.exists() && file.length() > 0){
- this.content = filePath;
- }else {
+ File file = ChapterService.getChapterFile(this);
+ if (file.exists() && file.length() > 0) {
+ this.content = file.getAbsolutePath();
+ } else {
this.content = null;
}
return this.content;
}
+
public void setContent(String content) {
this.content = content;
}
@@ -109,4 +162,61 @@ public class Chapter {
public void setEnd(long end) {
this.end = end;
}
+
+ public void putVariable(@NonNull String key, String value) {
+ if (variableMap == null) {
+ variableMap = new HashMap<>();
+ }
+ variableMap.put(key, value);
+ variable = GsonExtensionsKt.getGSON().toJson(variableMap);
+ }
+
+ @NonNull
+ public Map getVariableMap() {
+ if (variableMap == null && !TextUtils.isEmpty(variable)) {
+ variableMap = GsonExtensionsKt.getGSON().fromJson(variable, MAP_STRING);
+ }
+ if (variableMap == null) {
+ variableMap = new HashMap<>();
+ }
+ return variableMap;
+ }
+
+ @Nullable
+ @Override
+ public String getVariable(@NonNull String key) {
+ return getVariableMap().get(key);
+ }
+
+ public String getVariable() {
+ return this.variable;
+ }
+
+ public void setVariable(String variable) {
+ this.variable = variable;
+ }
+
+ public String getUpdateTime() {
+ return this.updateTime;
+ }
+
+ public void setUpdateTime(String updateTime) {
+ this.updateTime = updateTime;
+ }
+
+ public boolean getIsVip() {
+ return this.isVip;
+ }
+
+ public void setIsVip(boolean isVip) {
+ this.isVip = isVip;
+ }
+
+ public boolean getIsPay() {
+ return this.isPay;
+ }
+
+ public void setIsPay(boolean isPay) {
+ this.isPay = isPay;
+ }
}
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/CookieBean.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/CookieBean.java
index 5c4bd6c..ae12b46 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/CookieBean.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/CookieBean.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity;
import android.os.Parcel;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/ReadRecord.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/ReadRecord.java
index bbdb811..e00c5ac 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/ReadRecord.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/ReadRecord.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity;
import org.greenrobot.greendao.annotation.Entity;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/ReplaceRuleBean.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/ReplaceRuleBean.java
index 0710111..197e8e3 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/ReplaceRuleBean.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/ReplaceRuleBean.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity;
import android.os.Parcel;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/SearchHistory.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/SearchHistory.java
index 938dd11..7ea11c8 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/SearchHistory.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/SearchHistory.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity;
import org.greenrobot.greendao.annotation.Entity;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/SubscribeFile.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/SubscribeFile.java
new file mode 100644
index 0000000..00b3c25
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/SubscribeFile.java
@@ -0,0 +1,95 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.greendao.entity;
+
+import org.greenrobot.greendao.annotation.Entity;
+import org.greenrobot.greendao.annotation.Id;
+import org.greenrobot.greendao.annotation.Generated;
+
+/**
+ * @author fengyue
+ * @date 2022/3/3 14:40
+ */
+@Entity
+public class SubscribeFile {
+ @Id
+ private String id;
+
+ private String name;
+
+ private String url;
+
+ private String date;
+
+ private String size;
+
+ @Generated(hash = 1850023033)
+ public SubscribeFile(String id, String name, String url, String date,
+ String size) {
+ this.id = id;
+ this.name = name;
+ this.url = url;
+ this.date = date;
+ this.size = size;
+ }
+
+ @Generated(hash = 1590903919)
+ public SubscribeFile() {
+ }
+
+ public String getId() {
+ return this.id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getUrl() {
+ return this.url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getDate() {
+ return this.date;
+ }
+
+ public void setDate(String date) {
+ this.date = date;
+ }
+
+ public String getSize() {
+ return this.size;
+ }
+
+ public void setSize(String size) {
+ this.size = size;
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/BookListRule.kt b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/BookListRule.kt
new file mode 100644
index 0000000..8ce5211
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/BookListRule.kt
@@ -0,0 +1,32 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.greendao.entity.rule
+
+interface BookListRule {
+ var list: String?
+ var name: String?
+ var author: String?
+ var desc: String?
+ var type: String?
+ var lastChapter: String?
+ var updateTime: String?
+ var infoUrl: String?
+ var imgUrl: String?
+ var wordCount: String?
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/BookSource.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/BookSource.java
index 6f6b53d..ae125ed 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/BookSource.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/BookSource.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.rule;
import android.os.Parcel;
@@ -5,6 +23,7 @@ import android.os.Parcelable;
import android.text.TextUtils;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.google.gson.Gson;
@@ -24,6 +43,7 @@ import xyz.fycz.myreader.greendao.convert.FindRuleConvert;
import xyz.fycz.myreader.greendao.convert.InfoRuleConvert;
import xyz.fycz.myreader.greendao.convert.SearchRuleConvert;
import xyz.fycz.myreader.greendao.convert.TocRuleConvert;
+import xyz.fycz.myreader.model.third3.BaseSource;
import static xyz.fycz.myreader.util.utils.StringUtils.stringEquals;
@@ -32,7 +52,7 @@ import static xyz.fycz.myreader.util.utils.StringUtils.stringEquals;
* @date 2021/2/8 17:37
*/
@Entity
-public class BookSource implements Parcelable, Cloneable {
+public class BookSource extends BaseSource implements Parcelable, Cloneable {
//基本信息
@Id
private String sourceUrl;
@@ -43,7 +63,9 @@ public class BookSource implements Parcelable, Cloneable {
private String sourceType;
private String sourceHeaders;
private String loginUrl;
+ private String loginCheckJs;
private String sourceComment;
+ private String concurrentRate;
private Long lastUpdateTime;
@OrderBy
@@ -53,6 +75,8 @@ public class BookSource implements Parcelable, Cloneable {
private int weight;
private boolean enable;
+ private boolean noProxy;//不使用代理
+
@Transient
private transient ArrayList groupList;
@@ -72,12 +96,12 @@ public class BookSource implements Parcelable, Cloneable {
@Convert(converter = FindRuleConvert.class, columnType = String.class)
private FindRule findRule;
- @Generated(hash = 277037260)
+ @Generated(hash = 945434046)
public BookSource(String sourceUrl, String sourceEName, String sourceName, String sourceGroup,
- String sourceCharset, String sourceType, String sourceHeaders, String loginUrl,
- String sourceComment, Long lastUpdateTime, int orderNum, int weight, boolean enable,
- SearchRule searchRule, InfoRule infoRule, TocRule tocRule, ContentRule contentRule,
- FindRule findRule) {
+ String sourceCharset, String sourceType, String sourceHeaders, String loginUrl, String loginCheckJs,
+ String sourceComment, String concurrentRate, Long lastUpdateTime, int orderNum, int weight,
+ boolean enable, boolean noProxy, SearchRule searchRule, InfoRule infoRule, TocRule tocRule,
+ ContentRule contentRule, FindRule findRule) {
this.sourceUrl = sourceUrl;
this.sourceEName = sourceEName;
this.sourceName = sourceName;
@@ -86,11 +110,14 @@ public class BookSource implements Parcelable, Cloneable {
this.sourceType = sourceType;
this.sourceHeaders = sourceHeaders;
this.loginUrl = loginUrl;
+ this.loginCheckJs = loginCheckJs;
this.sourceComment = sourceComment;
+ this.concurrentRate = concurrentRate;
this.lastUpdateTime = lastUpdateTime;
this.orderNum = orderNum;
this.weight = weight;
this.enable = enable;
+ this.noProxy = noProxy;
this.searchRule = searchRule;
this.infoRule = infoRule;
this.tocRule = tocRule;
@@ -112,7 +139,9 @@ public class BookSource implements Parcelable, Cloneable {
sourceType = in.readString();
sourceHeaders = in.readString();
loginUrl = in.readString();
+ loginCheckJs = in.readString();
sourceComment = in.readString();
+ concurrentRate = in.readString();
if (in.readByte() == 0) {
lastUpdateTime = null;
} else {
@@ -121,6 +150,7 @@ public class BookSource implements Parcelable, Cloneable {
orderNum = in.readInt();
weight = in.readInt();
enable = in.readByte() != 0;
+ noProxy = in.readByte() != 0;
searchRule = in.readParcelable(SearchRule.class.getClassLoader());
infoRule = in.readParcelable(InfoRule.class.getClassLoader());
tocRule = in.readParcelable(TocRule.class.getClassLoader());
@@ -138,7 +168,9 @@ public class BookSource implements Parcelable, Cloneable {
dest.writeString(sourceType);
dest.writeString(sourceHeaders);
dest.writeString(loginUrl);
+ dest.writeString(loginCheckJs);
dest.writeString(sourceComment);
+ dest.writeString(concurrentRate);
if (lastUpdateTime == null) {
dest.writeByte((byte) 0);
} else {
@@ -148,6 +180,7 @@ public class BookSource implements Parcelable, Cloneable {
dest.writeInt(orderNum);
dest.writeInt(weight);
dest.writeByte((byte) (enable ? 1 : 0));
+ dest.writeByte((byte) (noProxy ? 1 : 0));
dest.writeParcelable(searchRule, flags);
dest.writeParcelable(infoRule, flags);
dest.writeParcelable(tocRule, flags);
@@ -178,6 +211,7 @@ public class BookSource implements Parcelable, Cloneable {
if (o == null || getClass() != o.getClass()) return false;
BookSource source = (BookSource) o;
return enable == source.enable &&
+ noProxy == source.noProxy &&
stringEquals(sourceUrl, source.sourceUrl) &&
stringEquals(sourceEName, source.sourceEName) &&
stringEquals(sourceName, source.sourceName) &&
@@ -186,7 +220,9 @@ public class BookSource implements Parcelable, Cloneable {
stringEquals(sourceType, source.sourceType) &&
stringEquals(sourceHeaders, source.sourceHeaders) &&
stringEquals(loginUrl, source.loginUrl) &&
+ stringEquals(loginCheckJs, source.loginCheckJs) &&
stringEquals(sourceComment, source.sourceComment) &&
+ stringEquals(concurrentRate, source.concurrentRate) &&
Objects.equals(searchRule, source.searchRule) &&
Objects.equals(infoRule, source.infoRule) &&
Objects.equals(tocRule, source.tocRule) &&
@@ -396,4 +432,62 @@ public class BookSource implements Parcelable, Cloneable {
public void setLoginUrl(String loginUrl) {
this.loginUrl = loginUrl;
}
+
+ public String getLoginCheckJs() {
+ return loginCheckJs;
+ }
+
+ public void setLoginCheckJs(String loginCheckJs) {
+ this.loginCheckJs = loginCheckJs;
+ }
+
+ public String getConcurrentRate() {
+ return this.concurrentRate;
+ }
+
+ public void setConcurrentRate(String concurrentRate) {
+ this.concurrentRate = concurrentRate;
+ }
+
+ @Nullable
+ @Override
+ public String getConcurrentRateKt() {
+ return concurrentRate;
+ }
+
+ @Nullable
+ @Override
+ public String getLoginUrlKt() {
+ return loginUrl;
+ }
+
+ @Override
+ public String getHeader() {
+ return sourceHeaders;
+ }
+
+ @NonNull
+ @Override
+ public String getTag() {
+ return sourceName;
+ }
+
+ @NonNull
+ @Override
+ public String getKey() {
+ return sourceUrl;
+ }
+
+ @Override
+ public BookSource getSource() {
+ return this;
+ }
+
+ public boolean getNoProxy() {
+ return this.noProxy;
+ }
+
+ public void setNoProxy(boolean noProxy) {
+ this.noProxy = noProxy;
+ }
}
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/ContentRule.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/ContentRule.java
index 71ba5ab..4ac83cb 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/ContentRule.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/ContentRule.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.rule;
import android.os.Parcel;
@@ -19,11 +37,17 @@ public class ContentRule implements Parcelable {
private String content;
private String contentBaseUrl;
private String contentUrlNext;
+ private String webJs;
+ private String sourceRegex;
+ private String replaceRegex;
protected ContentRule(Parcel in) {
content = in.readString();
contentBaseUrl = in.readString();
contentUrlNext = in.readString();
+ webJs = in.readString();
+ sourceRegex = in.readString();
+ replaceRegex = in.readString();
}
@Override
@@ -31,6 +55,9 @@ public class ContentRule implements Parcelable {
dest.writeString(content);
dest.writeString(contentBaseUrl);
dest.writeString(contentUrlNext);
+ dest.writeString(webJs);
+ dest.writeString(sourceRegex);
+ dest.writeString(replaceRegex);
}
@Override
@@ -58,7 +85,10 @@ public class ContentRule implements Parcelable {
ContentRule that = (ContentRule) o;
return stringEquals(content, that.content) &&
stringEquals(contentBaseUrl, that.contentBaseUrl) &&
- stringEquals(contentUrlNext, that.contentUrlNext);
+ stringEquals(contentUrlNext, that.contentUrlNext) &&
+ stringEquals(webJs, that.webJs) &&
+ stringEquals(sourceRegex, that.sourceRegex) &&
+ stringEquals(replaceRegex, that.replaceRegex);
}
@@ -89,5 +119,27 @@ public class ContentRule implements Parcelable {
this.contentUrlNext = contentUrlNext;
}
+ public String getWebJs() {
+ return webJs;
+ }
+
+ public void setWebJs(String webJs) {
+ this.webJs = webJs;
+ }
+
+ public String getSourceRegex() {
+ return sourceRegex;
+ }
+
+ public void setSourceRegex(String sourceRegex) {
+ this.sourceRegex = sourceRegex;
+ }
+ public String getReplaceRegex() {
+ return replaceRegex;
+ }
+
+ public void setReplaceRegex(String replaceRegex) {
+ this.replaceRegex = replaceRegex;
+ }
}
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/FindRule.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/FindRule.java
index 6e33326..3688c04 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/FindRule.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/FindRule.java
@@ -1,21 +1,35 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.rule;
import android.os.Parcel;
import android.os.Parcelable;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Objects;
-
import static xyz.fycz.myreader.util.utils.StringUtils.stringEquals;
/**
* @author fengyue
* @date 2021/2/10 8:57
*/
-public class FindRule implements Parcelable {
+public class FindRule implements Parcelable, BookListRule {
private String url;
- private String bookList;
+ private String list;
private String name;
private String author;
private String type;
@@ -33,7 +47,7 @@ public class FindRule implements Parcelable {
protected FindRule(Parcel in) {
url = in.readString();
- bookList = in.readString();
+ list = in.readString();
name = in.readString();
author = in.readString();
type = in.readString();
@@ -50,7 +64,7 @@ public class FindRule implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(url);
- dest.writeString(bookList);
+ dest.writeString(list);
dest.writeString(name);
dest.writeString(author);
dest.writeString(type);
@@ -89,12 +103,12 @@ public class FindRule implements Parcelable {
this.url = url;
}
- public String getBookList() {
- return bookList;
+ public String getList() {
+ return list;
}
- public void setBookList(String bookList) {
- this.bookList = bookList;
+ public void setList(String bookList) {
+ this.list = bookList;
}
public String getName() {
@@ -192,7 +206,7 @@ public class FindRule implements Parcelable {
if (getClass() != o.getClass()) return false;
FindRule findRule = (FindRule) o;
return stringEquals(url, findRule.url) &&
- stringEquals(bookList, findRule.bookList) &&
+ stringEquals(list, findRule.list) &&
stringEquals(name, findRule.name) &&
stringEquals(author, findRule.author) &&
stringEquals(type, findRule.type) &&
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/InfoRule.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/InfoRule.java
index b8029c3..037ca92 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/InfoRule.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/InfoRule.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.rule;
import android.os.Parcel;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/SearchRule.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/SearchRule.java
index bef4856..2a538ae 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/SearchRule.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/SearchRule.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.rule;
import android.os.Parcel;
@@ -17,7 +35,7 @@ import static xyz.fycz.myreader.util.utils.StringUtils.stringEquals;
* @author fengyue
* @date 2021/2/8 17:48
*/
-public class SearchRule implements Parcelable {
+public class SearchRule implements Parcelable, BookListRule {
private String searchUrl;
private String charset;
private String list;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/TocRule.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/TocRule.java
index fec6cb5..160b7d2 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/TocRule.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/TocRule.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.rule;
import android.os.Parcel;
@@ -22,6 +40,9 @@ public class TocRule implements Parcelable {
private String chapterName;
private String chapterUrl;
private String tocUrlNext;
+ private String isVip;
+ private String isPay;
+ private String updateTime;
protected TocRule(Parcel in) {
chapterList = in.readString();
@@ -29,6 +50,9 @@ public class TocRule implements Parcelable {
chapterName = in.readString();
chapterUrl = in.readString();
tocUrlNext = in.readString();
+ isVip = in.readString();
+ isPay = in.readString();
+ updateTime = in.readString();
}
@Override
@@ -38,6 +62,9 @@ public class TocRule implements Parcelable {
dest.writeString(chapterName);
dest.writeString(chapterUrl);
dest.writeString(tocUrlNext);
+ dest.writeString(isVip);
+ dest.writeString(isPay);
+ dest.writeString(updateTime);
}
@Override
@@ -67,7 +94,10 @@ public class TocRule implements Parcelable {
stringEquals(chapterBaseUrl, tocRule.chapterBaseUrl) &&
stringEquals(chapterName, tocRule.chapterName) &&
stringEquals(chapterUrl, tocRule.chapterUrl) &&
- stringEquals(tocUrlNext, tocRule.tocUrlNext);
+ stringEquals(tocUrlNext, tocRule.tocUrlNext) &&
+ stringEquals(isVip, tocRule.isVip) &&
+ stringEquals(isPay, tocRule.isPay) &&
+ stringEquals(updateTime, tocRule.updateTime);
}
public String getChapterList() {
@@ -110,6 +140,30 @@ public class TocRule implements Parcelable {
this.tocUrlNext = tocUrlNext;
}
+ public String getIsVip() {
+ return isVip;
+ }
+
+ public void setIsVip(String isVip) {
+ this.isVip = isVip;
+ }
+
+ public String getIsPay() {
+ return isPay;
+ }
+
+ public void setIsPay(String isPay) {
+ this.isPay = isPay;
+ }
+
+ public String getUpdateTime() {
+ return updateTime;
+ }
+
+ public void setUpdateTime(String updateTime) {
+ this.updateTime = updateTime;
+ }
+
public TocRule() {
}
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord.java b/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord.java
index e1dd58b..e629da6 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.search;
import org.greenrobot.greendao.annotation.Convert;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord1.kt b/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord1.kt
index e7f9051..16bf638 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord1.kt
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord1.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.search
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord2.kt b/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord2.kt
index 8eb1d09..2bcc1f2 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord2.kt
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/entity/search/SearchWord2.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.entity.search
/**
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BaseService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BaseService.java
index ad41666..81029c4 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BaseService.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BaseService.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.service;
import android.database.Cursor;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java
index 86a791f..ba6a84c 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.service;
import org.jetbrains.annotations.NotNull;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java
index 3a8c64e..6c4f20e 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookMarkService.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.service;
import xyz.fycz.myreader.greendao.DbManager;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java
index 241b54e..df2d00f 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookService.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.service;
import android.database.Cursor;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/CacheManager.kt b/app/src/main/java/xyz/fycz/myreader/greendao/service/CacheManager.kt
new file mode 100644
index 0000000..5b0fa0d
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/CacheManager.kt
@@ -0,0 +1,101 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.greendao.service
+
+import android.database.Cursor
+import xyz.fycz.myreader.application.App
+import xyz.fycz.myreader.greendao.DbManager
+import xyz.fycz.myreader.greendao.entity.Cache
+import xyz.fycz.myreader.model.third3.analyzeRule.QueryTTF
+import xyz.fycz.myreader.util.utils.ACache
+import java.lang.Exception
+
+
+@Suppress("unused")
+object CacheManager {
+
+ private val queryTTFMap = hashMapOf>()
+
+ /**
+ * saveTime 单位为秒
+ */
+ @JvmOverloads
+ fun put(key: String, value: Any, saveTime: Int = 0) {
+ val deadline =
+ if (saveTime == 0) 0 else System.currentTimeMillis() + saveTime * 1000
+ when (value) {
+ is QueryTTF -> queryTTFMap[key] = Pair(deadline, value)
+ is ByteArray -> ACache.get(App.getmContext()).put(key, value, saveTime)
+ else -> {
+ val cache = Cache(key, value.toString(), deadline)
+ DbManager.getDaoSession().cacheDao.insertOrReplace(cache)
+ }
+ }
+ }
+
+ fun get(key: String): String? {
+ var str: String? = null
+ try {
+ val sql = "select VALUE from CACHE where key = ? and (DEAD_LINE = 0 or DEAD_LINE > ?)"
+ val cursor: Cursor = DbManager.getDaoSession().database.rawQuery(
+ sql,
+ arrayOf(key, "" + System.currentTimeMillis())
+ ) ?: return null
+ if (cursor.moveToNext()) {
+ str = cursor.getColumnName(0)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ return str
+ }
+
+ fun getInt(key: String): Int? {
+ return get(key)?.toIntOrNull()
+ }
+
+ fun getLong(key: String): Long? {
+ return get(key)?.toLongOrNull()
+ }
+
+ fun getDouble(key: String): Double? {
+ return get(key)?.toDoubleOrNull()
+ }
+
+ fun getFloat(key: String): Float? {
+ return get(key)?.toFloatOrNull()
+ }
+
+ fun getByteArray(key: String): ByteArray? {
+ return ACache.get(App.getmContext()).getAsBinary(key)
+ }
+
+ fun getQueryTTF(key: String): QueryTTF? {
+ val cache = queryTTFMap[key] ?: return null
+ if (cache.first == 0L || cache.first > System.currentTimeMillis()) {
+ return cache.second
+ }
+ return null
+ }
+
+ fun delete(key: String) {
+ DbManager.getDaoSession().cacheDao.deleteByKey(key)
+ ACache.get(App.getmContext()).remove(key)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/ChapterService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/ChapterService.java
index c9e8c0c..20e1bbd 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/ChapterService.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/ChapterService.java
@@ -1,8 +1,27 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.service;
import android.database.Cursor;
import xyz.fycz.myreader.common.APPCONST;
+import xyz.fycz.myreader.greendao.entity.BookMark;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.gen.ChapterDao;
import xyz.fycz.myreader.util.IOUtils;
@@ -19,15 +38,16 @@ public class ChapterService extends BaseService {
private static volatile ChapterService sInstance;
public static ChapterService getInstance() {
- if (sInstance == null){
- synchronized (ChapterService.class){
- if (sInstance == null){
+ if (sInstance == null) {
+ synchronized (ChapterService.class) {
+ if (sInstance == null) {
sInstance = new ChapterService();
}
}
}
return sInstance;
}
+
private List findChapters(String sql, String[] selectionArgs) {
ArrayList chapters = new ArrayList<>();
try {
@@ -40,9 +60,12 @@ public class ChapterService extends BaseService {
chapter.setNumber(cursor.getInt(2));
chapter.setTitle(cursor.getString(3));
chapter.setUrl(cursor.getString(4));
- chapter.setContent(cursor.getString(5));
- chapter.setStart(cursor.getInt(6));
- chapter.setEnd(cursor.getInt(7));
+ chapter.setIsVip(cursor.getInt(5) != 0);
+ chapter.setIsPay(cursor.getInt(6) != 0);
+ chapter.setUpdateTime(cursor.getString(7));
+ chapter.setContent(cursor.getString(8));
+ chapter.setStart(cursor.getInt(9));
+ chapter.setEnd(cursor.getInt(10));
chapters.add(chapter);
}
} catch (Exception e) {
@@ -185,11 +208,11 @@ public class ChapterService extends BaseService {
return;
}
- File file = getBookFile(chapter.getBookId(), chapter.getTitle());
+ File file = getChapterFileExisted(chapter);
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
- bw.write(content.replace(chapter.getTitle(), ""));
+ bw.write(content);
bw.flush();
} catch (IOException e) {
e.printStackTrace();
@@ -204,25 +227,25 @@ public class ChapterService extends BaseService {
* @param chapter
*/
public void deleteChapterCacheFile(Chapter chapter) {
- File file = getBookFile(chapter.getBookId(), chapter.getTitle());
- file.delete();
+ File file = getChapterFile(chapter);
+ if (file.exists()) file.delete();
}
/**
* 获取缓存章节内容
+ *
* @param chapter
* @return
*/
- public String getChapterCatheContent(Chapter chapter){
- File file = new File(APPCONST.BOOK_CACHE_PATH + chapter.getBookId()
- + File.separator + chapter.getTitle() + FileUtils.SUFFIX_FY);
+ public String getChapterCatheContent(Chapter chapter) {
+ File file = getChapterFile(chapter);
if (!file.exists()) return null;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(file));
StringBuilder s = new StringBuilder();
String line = null;
- while ((line = br.readLine()) != null){
+ while ((line = br.readLine()) != null) {
s.append(line);
s.append("\n");
}
@@ -230,7 +253,7 @@ public class ChapterService extends BaseService {
} catch (IOException e) {
e.printStackTrace();
return null;
- }finally {
+ } finally {
IOUtils.close(br);
}
}
@@ -275,13 +298,20 @@ public class ChapterService extends BaseService {
* 根据文件名判断是否被缓存过 (因为可能数据库显示被缓存过,但是文件中却没有的情况,所以需要根据文件判断是否被缓存
* 过)
*
- * @param folderName : bookId
- * @param fileName: chapterName
+ * @param chapter : chapter
* @return
*/
- public static boolean isChapterCached(String folderName, String fileName) {
- File file = new File(APPCONST.BOOK_CACHE_PATH + folderName
- + File.separator + fileName + FileUtils.SUFFIX_FY);
+ public static boolean isChapterCached(Chapter chapter) {
+ File file = getChapterFile(chapter);
+ return file.exists();
+ }
+
+ public static boolean isChapterCached(BookMark bookMark) {
+ Chapter chapter = new Chapter();
+ chapter.setBookId(bookMark.getBookId());
+ chapter.setNumber(bookMark.getBookMarkChapterNum());
+ chapter.setTitle(bookMark.getTitle());
+ File file = getChapterFile(chapter);
return file.exists();
}
@@ -323,4 +353,24 @@ public class ChapterService extends BaseService {
+ File.separator + fileName + FileUtils.SUFFIX_FY);
}
+ public static File getChapterFile(Chapter chapter) {
+ File file = new File(APPCONST.BOOK_CACHE_PATH + chapter.getBookId()
+ + File.separator + chapter.getNumber() + "、" + chapter.getTitle() + FileUtils.SUFFIX_FY);
+ if (!file.exists()) {
+ file = new File(APPCONST.BOOK_CACHE_PATH + chapter.getBookId()
+ + File.separator + chapter.getTitle() + FileUtils.SUFFIX_FY);
+ }
+ return file;
+ }
+
+ public static File getChapterFileExisted(Chapter chapter) {
+ File file = new File(APPCONST.BOOK_CACHE_PATH + chapter.getBookId()
+ + File.separator + chapter.getTitle() + FileUtils.SUFFIX_FY);
+ if (!file.exists()) {
+ file = FileUtils.getFile(APPCONST.BOOK_CACHE_PATH + chapter.getBookId()
+ + File.separator + chapter.getNumber() + "、" + chapter.getTitle() + FileUtils.SUFFIX_FY);
+ }
+ return file;
+ }
+
}
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/CookieStore.kt b/app/src/main/java/xyz/fycz/myreader/greendao/service/CookieStore.kt
index 1f23a28..84e917a 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/CookieStore.kt
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/CookieStore.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
@file:Suppress("unused")
package xyz.fycz.myreader.greendao.service
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/ReadRecordService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/ReadRecordService.java
index 736be87..53efda6 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/ReadRecordService.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/ReadRecordService.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.service;
import java.util.List;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/SearchHistoryService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/SearchHistoryService.java
index 80dc837..e9d397f 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/SearchHistoryService.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/SearchHistoryService.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.service;
import android.database.Cursor;
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/api/CookieManager.kt b/app/src/main/java/xyz/fycz/myreader/greendao/service/api/CookieManager.kt
index 0625ff1..d368698 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/service/api/CookieManager.kt
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/api/CookieManager.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.service.api
interface CookieManager {
diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/util/MySQLiteOpenHelper.java b/app/src/main/java/xyz/fycz/myreader/greendao/util/MySQLiteOpenHelper.java
index bcc4dd4..9537a90 100644
--- a/app/src/main/java/xyz/fycz/myreader/greendao/util/MySQLiteOpenHelper.java
+++ b/app/src/main/java/xyz/fycz/myreader/greendao/util/MySQLiteOpenHelper.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.greendao.util;
import android.content.Context;
@@ -39,7 +57,7 @@ public class MySQLiteOpenHelper extends DaoMaster.OpenHelper {
BookDao.class, ChapterDao.class, SearchHistoryDao.class,
BookMarkDao.class, BookGroupDao.class, ReplaceRuleBeanDao.class,
BookSourceDao.class, CookieBeanDao.class, ReadRecordDao.class,
- SearchWordDao.class
+ SearchWordDao.class, SubscribeFileDao.class
);
}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/ReplaceRuleManager.java b/app/src/main/java/xyz/fycz/myreader/model/ReplaceRuleManager.java
index db47421..6c4c975 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/ReplaceRuleManager.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/ReplaceRuleManager.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java b/app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java
index e920016..bec483e 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/SearchEngine.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model;
@@ -45,11 +63,12 @@ public class SearchEngine {
private int searchSiteIndex;
private int searchSuccessNum;
private int searchFinishNum;
+ private boolean isFinish;
private OnSearchListener searchListener;
public SearchEngine() {
- threadsNum = SharedPreUtils.getInstance().getInt(App.getmContext().getString(R.string.threadNum), 8);
+ threadsNum = SharedPreUtils.getInstance().getInt(App.getmContext().getString(R.string.threadNum), 16);
}
public void setOnSearchListener(OnSearchListener searchListener) {
@@ -70,6 +89,7 @@ public class SearchEngine {
public void stopSearch() {
if (compositeDisposable != null) compositeDisposable.dispose();
compositeDisposable = new CompositeDisposable();
+ isFinish = true;
searchListener.loadMoreFinish(true);
}
@@ -109,6 +129,7 @@ public class SearchEngine {
searchSuccessNum = 0;
searchSiteIndex = -1;
searchFinishNum = 0;
+ isFinish = false;
for (int i = 0; i < Math.min(mSourceList.size(), threadsNum); i++) {
searchOnEngine(keyword);
}
@@ -130,6 +151,7 @@ public class SearchEngine {
searchSuccessNum = 0;
searchSiteIndex = -1;
searchFinishNum = 0;
+ isFinish = false;
for (int i = 0; i < Math.min(mSourceList.size(), threadsNum); i++) {
searchOnEngine(title, author);
}
@@ -139,6 +161,7 @@ public class SearchEngine {
searchSiteIndex++;
if (searchSiteIndex < mSourceList.size()) {
ReadCrawler crawler = mSourceList.get(searchSiteIndex);
+ //BookApi.search(keyword, crawler, executorService)
BookApi.search(keyword, crawler)
.subscribeOn(scheduler)
.observeOn(AndroidSchedulers.mainThread())
@@ -170,8 +193,9 @@ public class SearchEngine {
}
});
- } else {
+ } else if (!isFinish){
if (searchFinishNum == mSourceList.size()) {
+ isFinish = true;
if (searchSuccessNum == 0) {
searchListener.searchBookError(new Throwable("未搜索到内容"));
}
@@ -186,6 +210,7 @@ public class SearchEngine {
if (searchSiteIndex < mSourceList.size()) {
ReadCrawler crawler = mSourceList.get(searchSiteIndex);
String searchKey = title;
+ //BookApi.search(searchKey, crawler, executorService)
BookApi.search(searchKey, crawler)
.subscribeOn(scheduler)
.observeOn(AndroidSchedulers.mainThread())
@@ -220,13 +245,13 @@ public class SearchEngine {
}
});
- } else {
+ } else if (!isFinish){
if (searchFinishNum >= mSourceList.size()) {
+ isFinish = true;
if (searchSuccessNum == 0) {
searchListener.searchBookError(new Throwable("未搜索到内容"));
}
searchListener.loadMoreFinish(true);
-
}
}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/SearchWordEngine.kt b/app/src/main/java/xyz/fycz/myreader/model/SearchWordEngine.kt
index a3fd4ca..3910f06 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/SearchWordEngine.kt
+++ b/app/src/main/java/xyz/fycz/myreader/model/SearchWordEngine.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model
import io.reactivex.*
@@ -108,7 +126,7 @@ class SearchWordEngine(
chapterTitle = chapter.title,
searchWord2List = mutableListOf()
)
- if (!isLocalBook && !ChapterService.isChapterCached(book.id, chapter.title)) {
+ if (!isLocalBook && !ChapterService.isChapterCached(chapter)) {
emitter.onNext(searchWord1)
return@ObservableOnSubscribe
}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/audio/AudioPlayer.java b/app/src/main/java/xyz/fycz/myreader/model/audio/AudioPlayer.java
index 4d8892d..6d72daf 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/audio/AudioPlayer.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/audio/AudioPlayer.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.audio;
import android.media.AudioFormat;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/audio/ReadAloudService.java b/app/src/main/java/xyz/fycz/myreader/model/audio/ReadAloudService.java
index 63478a7..60c47fc 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/audio/ReadAloudService.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/audio/ReadAloudService.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.audio;
import android.app.Notification;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/ConMVMap.java b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/ConMVMap.java
index 85e1a74..da39e47 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/ConMVMap.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/ConMVMap.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.mulvalmap;
import java.util.*;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/LinkedMultiValueMap.java b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/LinkedMultiValueMap.java
index 6ae3ce3..fa94d67 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/LinkedMultiValueMap.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/LinkedMultiValueMap.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.mulvalmap;
import java.util.ArrayList;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueMap.java b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueMap.java
index 928dae6..3cbdc2e 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueMap.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueMap.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.mulvalmap;
import java.util.List;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueSetMap.java b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueSetMap.java
index 18bdaa6..33d3c7c 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueSetMap.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/mulvalmap/MultiValueSetMap.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.mulvalmap;
import java.util.*;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BaseAnalyzer.java b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BaseAnalyzer.java
index 01620f4..72c184a 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BaseAnalyzer.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BaseAnalyzer.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.sourceAnalyzer;
import android.util.Log;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BookSourceManager.java b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BookSourceManager.java
index 2985c0c..899f4f8 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BookSourceManager.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/BookSourceManager.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.sourceAnalyzer;
import android.database.Cursor;
@@ -11,17 +29,22 @@ import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableSource;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
+import io.reactivex.functions.Function;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App;
-import xyz.fycz.myreader.entity.thirdsource.BookSource3Bean;
import xyz.fycz.myreader.entity.thirdsource.BookSourceBean;
import xyz.fycz.myreader.entity.thirdsource.ThirdSourceUtil;
+import xyz.fycz.myreader.entity.thirdsource.source3.Source3;
+import xyz.fycz.myreader.entity.thirdsource.source3.Third3SourceUtil;
import xyz.fycz.myreader.enums.LocalBookSource;
import xyz.fycz.myreader.greendao.DbManager;
+import xyz.fycz.myreader.greendao.entity.SubscribeFile;
import xyz.fycz.myreader.greendao.entity.rule.BookSource;
import xyz.fycz.myreader.greendao.gen.BookSourceDao;
+import xyz.fycz.myreader.model.third3.SourceAnalyzer;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.help.StringHelper;
import xyz.fycz.myreader.util.utils.FileUtils;
@@ -31,6 +54,7 @@ import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.OkHttpUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
+import xyz.fycz.myreader.webapi.LanZouApi;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
@@ -162,14 +186,37 @@ public class BookSourceManager {
.list();
}
+
+ public static List getAllSubSource() {
+ return DbManager.getDaoSession().getBookSourceDao().queryBuilder()
+ .where(BookSourceDao.Properties.SourceEName.isNotNull())
+ .where(BookSourceDao.Properties.SourceType.isNotNull())
+ .orderAsc(BookSourceDao.Properties.OrderNum)
+ .list();
+ }
+
/**
- * 获取所有导入书源
+ * 获取所有非内置书源
*
* @return
*/
public static List getAllNoLocalSource() {
return DbManager.getDaoSession().getBookSourceDao().queryBuilder()
.where(BookSourceDao.Properties.SourceEName.isNull())
+ .where(BookSourceDao.Properties.SourceType.isNotNull())
+ .orderAsc(BookSourceDao.Properties.OrderNum)
+ .list();
+ }
+
+ public static void removeSourceBySubscribe(SubscribeFile file) {
+ DbManager.getDaoSession().getBookSourceDao().queryBuilder()
+ .where(BookSourceDao.Properties.SourceEName.eq("订阅书源:" + file.getId()))
+ .buildDelete().executeDeleteWithoutDetachingEntities();
+ }
+
+ public static List getSourceBySubscribe(SubscribeFile file) {
+ return DbManager.getDaoSession().getBookSourceDao().queryBuilder()
+ .where(BookSourceDao.Properties.SourceEName.eq("订阅书源:" + file.getId()))
.orderAsc(BookSourceDao.Properties.OrderNum)
.list();
}
@@ -189,6 +236,10 @@ public class BookSourceManager {
DbManager.getDaoSession().getBookSourceDao().deleteInTx(sources);
}
+ public static boolean isBookSourceExist(BookSource source) {
+ if (source == null) return false;
+ return DbManager.getDaoSession().getBookSourceDao().load(source.getSourceUrl()) != null;
+ }
public static String getBookSourceSort() {
switch (SharedPreUtils.getInstance().getInt("SourceSort", 0)) {
@@ -259,7 +310,7 @@ public class BookSourceManager {
}).compose(RxUtils::toSimpleSingle);
}
- public static List getEnableNoLocalGroupList() {
+ public static List getEnableGroupList() {
List groupList = new ArrayList<>();
String sql = "SELECT DISTINCT "
+ BookSourceDao.Properties.SourceGroup.columnName
@@ -280,17 +331,24 @@ public class BookSourceManager {
return groupList;
}
- public static List getNoLocalGroupList() {
+ public static List getGroupList(boolean isSubscribe) {
List groupList = new ArrayList<>();
- String sql = "SELECT DISTINCT " + BookSourceDao.Properties.SourceGroup.columnName + " FROM " + BookSourceDao.TABLENAME;
+ String sql = "SELECT DISTINCT " + BookSourceDao.Properties.SourceGroup.columnName + ","
+ + BookSourceDao.Properties.SourceEName.columnName + " FROM " + BookSourceDao.TABLENAME;
Cursor cursor = DbManager.getDaoSession().getDatabase().rawQuery(sql, null);
if (!cursor.moveToFirst()) return groupList;
do {
String group = cursor.getString(0);
+ String eName = cursor.getString(1);
if (TextUtils.isEmpty(group) || TextUtils.isEmpty(group.trim())) continue;
for (String item : group.split("\\s*[,;,;]\\s*")) {
- if (TextUtils.isEmpty(item) || groupList.contains(item) || item.equals("内置书源"))
- continue;
+ if (isSubscribe) {
+ if (TextUtils.isEmpty(eName) || TextUtils.isEmpty(item) || groupList.contains(item) || item.equals("内置书源"))
+ continue;
+ } else {
+ if (!TextUtils.isEmpty(eName) || TextUtils.isEmpty(item) || groupList.contains(item) || item.equals("内置书源"))
+ continue;
+ }
groupList.add(item);
}
} while (cursor.moveToNext());
@@ -298,36 +356,50 @@ public class BookSourceManager {
return groupList;
}
- public static Observable> importSource(String string) {
+ public static Observable> importSource(String string, String subscribeId) {
if (StringHelper.isEmpty(string)) return null;
string = string.trim();
if (NetworkUtils.isIPv4Address(string)) {
string = String.format("http://%s:65501", string);
}
if (StringUtils.isJsonType(string)) {
- return importBookSourceFromJson(string.trim())
+ return importBookSourceFromJson(string.trim(), subscribeId)
.compose(RxUtils::toSimpleSingle);
} else if (StringUtils.isCompressJsonType(string)) {
- return importBookSourceFromJson(StringUtils.unCompressJson(string))
+ return importBookSourceFromJson(StringUtils.unCompressJson(string), subscribeId)
.compose(RxUtils::toSimpleSingle);
} else if (new File(string).isFile()) {
- return importSource(FileUtils.readText(string));
+ return importSource(FileUtils.readText(string), subscribeId);
+ }
+ if (string.matches("https://.+\\.lanzou[a-z]\\.com/[\\s\\S]*")) {
+ return LanZouApi.INSTANCE.getFileUrl(string)
+ .flatMap((Function>) s -> Observable.create(emitter -> {
+ emitter.onNext(OkHttpUtils.getHtml(s));
+ emitter.onComplete();
+ })).flatMap(json -> importBookSourceFromJson(json, subscribeId))
+ .compose(RxUtils::toSimpleSingle);
}
if (NetworkUtils.isUrl(string)) {
String finalString = string;
return Observable.create((ObservableEmitter e) -> e.onNext(OkHttpUtils.getHtml(finalString)))
- .flatMap(BookSourceManager::importBookSourceFromJson)
+ .flatMap(json -> importBookSourceFromJson(json, subscribeId))
.compose(RxUtils::toSimpleSingle);
}
return Observable.error(new Exception("不是Json或Url格式或文件路径"));
}
private static Observable> importBookSourceFromJson(String json) {
+ return importBookSourceFromJson(json, "");
+ }
+
+ private static Observable> importBookSourceFromJson(String json, String subscribeId) {
return Observable.create(emitter -> {
List successImportSources = new ArrayList<>();
List bookSources = importSources(json);
if (bookSources != null) {
for (BookSource bookSource : bookSources) {
+ if (!TextUtils.isEmpty(subscribeId))
+ bookSource.setSourceEName("订阅书源:" + subscribeId);
if (bookSource.containsGroup("删除")) {
DbManager.getDaoSession().getBookSourceDao().queryBuilder()
.where(BookSourceDao.Properties.SourceUrl.eq(bookSource.getSourceUrl()))
@@ -355,16 +427,17 @@ public class BookSourceManager {
return sources;
}
+ List source3s = SourceAnalyzer.INSTANCE.jsonToBookSources(json);
+ String source3sJson = GsonExtensionsKt.getGSON().toJson(source3s);
+ if (source3s.size() > 0 && source3sJson.length() > source3s.size() * SOURCE_LENGTH) {
+ return Third3SourceUtil.INSTANCE.source3sToSources(source3s);
+ }
+
List source2s = GsonUtils.parseJArray(json, BookSourceBean.class);
String source2sJson = GsonExtensionsKt.getGSON().toJson(source2s);
if (source2s.size() > 0 && source2sJson.length() > source2s.size() * SOURCE_LENGTH) {
return ThirdSourceUtil.source2sToSources(source2s);
}
- List source3s = GsonUtils.parseJArray(json, BookSource3Bean.class);
- String source3sJson = GsonExtensionsKt.getGSON().toJson(source3s);
- if (source3s.size() > 0 && source3sJson.length() > source3s.size() * SOURCE_LENGTH) {
- return ThirdSourceUtil.source3sToSources(source3s);
- }
} catch (Exception e) {
e.printStackTrace();
}
@@ -379,6 +452,13 @@ public class BookSourceManager {
return sources;
}
+ Source3 source3 = SourceAnalyzer.INSTANCE.jsonToBookSource(json);
+ String source3Json = GsonExtensionsKt.getGSON().toJson(source3);
+ if (!StringHelper.isEmpty(source3Json) && source3Json.length() > SOURCE_LENGTH) {
+ sources.add(Third3SourceUtil.INSTANCE.source3ToSource(source3));
+ return sources;
+ }
+
BookSourceBean source2 = GsonUtils.parseJObject(json, BookSourceBean.class);
String source2Json = GsonExtensionsKt.getGSON().toJson(source2);
if (!StringHelper.isEmpty(source2Json) && source2Json.length() > SOURCE_LENGTH) {
@@ -386,12 +466,6 @@ public class BookSourceManager {
return sources;
}
- BookSource3Bean source3 = GsonUtils.parseJObject(json, BookSource3Bean.class);
- String source3Json = GsonExtensionsKt.getGSON().toJson(source3);
- if (!StringHelper.isEmpty(source3Json) && source3Json.length() > SOURCE_LENGTH) {
- sources.add(ThirdSourceUtil.source3ToSource(source3));
- return sources;
- }
} catch (Exception e) {
e.printStackTrace();
}
@@ -403,14 +477,13 @@ public class BookSourceManager {
Log.d("initDefaultSources", "execute");
DbManager.getDaoSession().getBookSourceDao().deleteAll();
String searchSource = SharedPreUtils.getInstance().getString(App.getmContext().getString(R.string.searchSource));
- boolean isEmpty = StringHelper.isEmpty(searchSource);
for (LocalBookSource source : LocalBookSource.values()) {
if (source == LocalBookSource.local || source == LocalBookSource.fynovel) continue;
BookSource source1 = new BookSource();
source1.setSourceEName(source.toString());
source1.setSourceName(source.text);
source1.setSourceGroup("内置书源");
- source1.setEnable(isEmpty || searchSource.contains(source.toString()));
+ source1.setEnable(false);
source1.setSourceUrl(ReadCrawlerUtil.getReadCrawlerClz(source.toString()));
source1.setOrderNum(0);
DbManager.getDaoSession().getBookSourceDao().insertOrReplace(source1);
diff --git a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/JsonPathAnalyzer.java b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/JsonPathAnalyzer.java
index 1382696..e08f1ad 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/JsonPathAnalyzer.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/JsonPathAnalyzer.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.sourceAnalyzer;
import com.google.gson.JsonArray;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/MatcherAnalyzer.java b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/MatcherAnalyzer.java
index e2ce9b0..177573f 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/MatcherAnalyzer.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/MatcherAnalyzer.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.sourceAnalyzer;
import java.util.ArrayList;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/XpathAnalyzer.java b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/XpathAnalyzer.java
index 249099c..217adb3 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/XpathAnalyzer.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/sourceAnalyzer/XpathAnalyzer.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.sourceAnalyzer;
import org.seimicrawler.xpath.JXDocument;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/storage/Backup.kt b/app/src/main/java/xyz/fycz/myreader/model/storage/Backup.kt
index 6a6865f..8124e9d 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/storage/Backup.kt
+++ b/app/src/main/java/xyz/fycz/myreader/model/storage/Backup.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.storage
import android.content.Context
@@ -43,6 +61,7 @@ object Backup {
"bookSource.json",
"readRecord.json",
"searchWord.json",
+ "subscribe.json",
"config.xml"
)
}
@@ -137,6 +156,13 @@ object Backup {
.writeText(json)
}
}
+ DbManager.getDaoSession().subscribeFileDao.queryBuilder().list().let {
+ if (it.isNotEmpty()) {
+ val json = GSON.toJson(it)
+ FileUtils.getFile(backupPath + File.separator + "subscribe.json")
+ .writeText(json)
+ }
+ }
try {
val setting = SysManager.getNewSetting()
val readStyles = setting.readStyles
diff --git a/app/src/main/java/xyz/fycz/myreader/model/storage/BackupRestoreUi.kt b/app/src/main/java/xyz/fycz/myreader/model/storage/BackupRestoreUi.kt
index 55f9d96..914041f 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/storage/BackupRestoreUi.kt
+++ b/app/src/main/java/xyz/fycz/myreader/model/storage/BackupRestoreUi.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.storage
import android.app.Activity
diff --git a/app/src/main/java/xyz/fycz/myreader/model/storage/Preferences.kt b/app/src/main/java/xyz/fycz/myreader/model/storage/Preferences.kt
index 9cd354c..5955cc9 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/storage/Preferences.kt
+++ b/app/src/main/java/xyz/fycz/myreader/model/storage/Preferences.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.storage
import android.app.Activity
diff --git a/app/src/main/java/xyz/fycz/myreader/model/storage/Restore.kt b/app/src/main/java/xyz/fycz/myreader/model/storage/Restore.kt
index e018276..2ceb814 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/storage/Restore.kt
+++ b/app/src/main/java/xyz/fycz/myreader/model/storage/Restore.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.storage
import android.content.Context
@@ -139,6 +157,15 @@ object Restore {
} catch (e: Exception) {
e.printStackTrace()
}
+ try {
+ val file = FileUtils.getFile(path + File.separator + "subscribe.json")
+ val json = file.readText()
+ GSON.fromJsonArray(json)?.let {
+ DbManager.getInstance().session.subscribeFileDao.insertOrReplaceInTx(it)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
try {
val settingFile = FileUtils.getFile(path + File.separator + "setting.json")
val settingJson = settingFile.readText()
diff --git a/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt b/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt
index 64f0f52..dcb19c5 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt
+++ b/app/src/main/java/xyz/fycz/myreader/model/storage/WebDavHelp.kt
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.storage
import android.os.Handler
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByJSonPath.java b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByJSonPath.java
index 39ecab5..d878abc 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByJSonPath.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByJSonPath.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.analyzeRule;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByJSoup.java b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByJSoup.java
index 620eae2..4dfaa5f 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByJSoup.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByJSoup.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.analyzeRule;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByRegex.java b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByRegex.java
index 922d9fc..0f4aa01 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByRegex.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByRegex.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.analyzeRule;
import android.os.Build;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByXPath.java b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByXPath.java
index f86dda4..3a1c359 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByXPath.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeByXPath.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.analyzeRule;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeRule.java b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeRule.java
index 2cf42c8..b6d68ca 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeRule.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeRule.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.analyzeRule;
import android.annotation.SuppressLint;
@@ -20,7 +38,6 @@ import javax.script.SimpleBindings;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.service.CookieStore;
import xyz.fycz.myreader.util.help.StringHelper;
-import xyz.fycz.myreader.util.help.JsExtensions;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeUrl.java b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeUrl.java
index 2bd7c25..6e23d14 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeUrl.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/AnalyzeUrl.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.analyzeRule;
import android.annotation.SuppressLint;
@@ -20,7 +38,6 @@ import java.util.regex.Pattern;
import javax.script.SimpleBindings;
import xyz.fycz.myreader.util.help.StringHelper;
-import xyz.fycz.myreader.util.help.JsExtensions;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
import xyz.fycz.myreader.util.utils.UrlEncoderUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/util/help/JsExtensions.java b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/JsExtensions.java
similarity index 88%
rename from app/src/main/java/xyz/fycz/myreader/util/help/JsExtensions.java
rename to app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/JsExtensions.java
index 7b8a674..ad61a95 100644
--- a/app/src/main/java/xyz/fycz/myreader/util/help/JsExtensions.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/JsExtensions.java
@@ -1,4 +1,22 @@
-package xyz.fycz.myreader.util.help;
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third2.analyzeRule;
import android.text.TextUtils;
@@ -23,10 +41,9 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import xyz.fycz.myreader.greendao.service.CookieStore;
-import xyz.fycz.myreader.model.third2.analyzeRule.AnalyzeUrl;
import xyz.fycz.myreader.util.ZipUtils;
+import xyz.fycz.myreader.util.help.SSLSocketClient;
import xyz.fycz.myreader.util.utils.EncoderUtils;
-import xyz.fycz.myreader.util.utils.EncodingDetect;
import xyz.fycz.myreader.util.utils.FileUtils;
import xyz.fycz.myreader.util.utils.MD5Utils;
import xyz.fycz.myreader.util.utils.OkHttpUtils;
@@ -253,7 +270,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
- default byte[] aesDecodeToByteArray(String str, String key, String transformation, String iv) {
+ default byte[] aesDecodeToByteArray(String str, String key, String transformation, String iv) throws Exception {
return EncoderUtils.INSTANCE.decryptAES(
str.getBytes(StandardCharsets.UTF_8),
@@ -263,7 +280,7 @@ public interface JsExtensions {
);
}
- default byte[] aesDecodeToByteArray(String str, String key, String transformation) {
+ default byte[] aesDecodeToByteArray(String str, String key, String transformation) throws Exception {
return aesDecodeToByteArray(str, key, transformation, "");
}
@@ -276,7 +293,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量
*/
- default String aesDecodeToString(String str, String key, String transformation, String iv) {
+ default String aesDecodeToString(String str, String key, String transformation, String iv) throws Exception {
byte[] bytes = aesDecodeToByteArray(str, key, transformation, iv);
if (bytes == null) {
return "";
@@ -284,7 +301,7 @@ public interface JsExtensions {
return new String(bytes);
}
- default String aesDecodeToString(String str, String key, String transformation) {
+ default String aesDecodeToString(String str, String key, String transformation) throws Exception {
return aesDecodeToString(str, key, transformation, "");
}
@@ -297,7 +314,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量
*/
- default byte[] aesBase64DecodeToByteArray(String str, String key, String transformation, String iv) {
+ default byte[] aesBase64DecodeToByteArray(String str, String key, String transformation, String iv) throws Exception {
return EncoderUtils.INSTANCE.decryptBase64AES(
str.getBytes(StandardCharsets.UTF_8),
key.getBytes(StandardCharsets.UTF_8),
@@ -306,7 +323,7 @@ public interface JsExtensions {
);
}
- default byte[] aesBase64DecodeToByteArray(String str, String key, String transformation) {
+ default byte[] aesBase64DecodeToByteArray(String str, String key, String transformation) throws Exception {
return aesBase64DecodeToByteArray(str, key, transformation, "");
}
@@ -320,7 +337,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量
*/
- default String aesBase64DecodeToString(String str, String key, String transformation, String iv) {
+ default String aesBase64DecodeToString(String str, String key, String transformation, String iv) throws Exception {
byte[] bytes = aesBase64DecodeToByteArray(str, key, transformation, iv);
if (bytes == null) {
return "";
@@ -328,7 +345,7 @@ public interface JsExtensions {
return new String(bytes);
}
- default String aesBase64DecodeToString(String str, String key, String transformation) {
+ default String aesBase64DecodeToString(String str, String key, String transformation) throws Exception {
return aesBase64DecodeToString(str, key, transformation, "");
}
@@ -340,7 +357,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
- default byte[] aesEncodeToByteArray(String data, String key, String transformation, String iv) {
+ default byte[] aesEncodeToByteArray(String data, String key, String transformation, String iv) throws Exception {
return EncoderUtils.INSTANCE.encryptAES(
data.getBytes(StandardCharsets.UTF_8),
key.getBytes(StandardCharsets.UTF_8),
@@ -349,7 +366,7 @@ public interface JsExtensions {
);
}
- default byte[] aesEncodeToByteArray(String data, String key, String transformation) {
+ default byte[] aesEncodeToByteArray(String data, String key, String transformation) throws Exception {
return aesEncodeToByteArray(data, key, transformation, "");
}
@@ -361,7 +378,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
- default String aesEncodeToString(String data, String key, String transformation, String iv) {
+ default String aesEncodeToString(String data, String key, String transformation, String iv) throws Exception {
byte[] bytes = aesEncodeToByteArray(data, key, transformation, iv);
if (bytes == null) {
return "";
@@ -369,7 +386,7 @@ public interface JsExtensions {
return new String(bytes);
}
- default String aesEncodeToString(String str, String key, String transformation) {
+ default String aesEncodeToString(String str, String key, String transformation) throws Exception {
return aesEncodeToString(str, key, transformation, "");
}
@@ -381,7 +398,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
- default byte[] aesEncodeToBase64ByteArray(String data, String key, String transformation, String iv) {
+ default byte[] aesEncodeToBase64ByteArray(String data, String key, String transformation, String iv) throws Exception {
return EncoderUtils.INSTANCE.encryptAES2Base64(
data.getBytes(StandardCharsets.UTF_8),
key.getBytes(StandardCharsets.UTF_8),
@@ -390,7 +407,7 @@ public interface JsExtensions {
);
}
- default byte[] aesEncodeToBase64ByteArray(String data, String key, String transformation) {
+ default byte[] aesEncodeToBase64ByteArray(String data, String key, String transformation) throws Exception {
return aesEncodeToBase64ByteArray(data, key, transformation, "");
}
@@ -402,7 +419,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
- default String aesEncodeToBase64String(String data, String key, String transformation, String iv) {
+ default String aesEncodeToBase64String(String data, String key, String transformation, String iv) throws Exception {
byte[] bytes = aesEncodeToBase64ByteArray(data, key, transformation, iv);
if (bytes == null) {
return "";
@@ -410,7 +427,7 @@ public interface JsExtensions {
return new String(bytes);
}
- default String aesEncodeToBase64String(String str, String key, String transformation) {
+ default String aesEncodeToBase64String(String str, String key, String transformation) throws Exception {
return aesEncodeToBase64String(str, key, transformation, "");
}
}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/content/AnalyzeNextUrlTask.java b/app/src/main/java/xyz/fycz/myreader/model/third2/content/AnalyzeNextUrlTask.java
index ef87498..e8ad30d 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/content/AnalyzeNextUrlTask.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/content/AnalyzeNextUrlTask.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.content;
import java.util.List;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookChapterList.java b/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookChapterList.java
index 08bfb0f..9504d80 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookChapterList.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookChapterList.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.content;
import android.os.Build;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookContent.java b/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookContent.java
index 1942c8b..6e40c27 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookContent.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookContent.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.content;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookInfo.java b/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookInfo.java
index a01a2c7..5b23d81 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookInfo.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookInfo.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.content;
import android.text.TextUtils;
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookList.java b/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookList.java
index dff9157..32ef8d7 100644
--- a/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookList.java
+++ b/app/src/main/java/xyz/fycz/myreader/model/third2/content/BookList.java
@@ -1,3 +1,21 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
package xyz.fycz.myreader.model.third2.content;
import android.os.Build;
@@ -147,9 +165,9 @@ public class BookList {
}
private void initRule() {
- if (isFind && !TextUtils.isEmpty(bookSource.getFindRule().getBookList())) {
+ if (isFind && !TextUtils.isEmpty(bookSource.getFindRule().getList())) {
FindRule findRule = bookSource.getFindRule();
- ruleList = findRule.getBookList();
+ ruleList = findRule.getList();
ruleName = findRule.getName();
ruleAuthor = findRule.getAuthor();
ruleKind = findRule.getType();
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/BaseSource.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/BaseSource.kt
new file mode 100644
index 0000000..e5cea19
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/BaseSource.kt
@@ -0,0 +1,192 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3
+
+import android.util.Base64
+import android.util.Log
+import xyz.fycz.myreader.common.APPCONST
+import xyz.fycz.myreader.greendao.service.CacheManager
+import xyz.fycz.myreader.greendao.service.CookieStore
+import xyz.fycz.myreader.model.third3.analyzeRule.JsExtensions
+import xyz.fycz.myreader.util.utils.EncoderUtils
+import xyz.fycz.myreader.util.utils.GSON
+import xyz.fycz.myreader.util.utils.fromJsonObject
+import javax.script.SimpleBindings
+
+/**
+ * 可在js里调用,source.xxx()
+ */
+@Suppress("unused")
+abstract class BaseSource : JsExtensions {
+
+ //var concurrentRate: String? // 并发率
+ //var loginUrl: String? // 登录地址
+ //var loginUi: String? // 登录UI
+ //var header: String? // 请求头
+
+ open fun getConcurrentRateKt(): String? = null // 并发率
+
+ open fun getLoginUrlKt(): String? = null // 登录地址
+
+ open fun getHeader(): String? = null // 请求头
+
+ open fun getTag(): String = ""
+
+ open fun getKey(): String = ""
+
+ open fun getNoProxy(): Boolean = false
+
+ /*fun loginUi(): List? {
+ return GSON.fromJsonArray(loginUi)
+ }*/
+
+ fun getLoginJs(): String? {
+ val loginJs = getLoginUrlKt()
+ return when {
+ loginJs == null -> null
+ loginJs.startsWith("@js:") -> loginJs.substring(4)
+ loginJs.startsWith("") ->
+ loginJs.substring(4, loginJs.lastIndexOf("<"))
+ else -> loginJs
+ }
+ }
+
+ fun login() {
+ getLoginJs()?.let {
+ evalJS(it)
+ }
+ }
+
+ /**
+ * 解析header规则
+ */
+ fun getHeaderMap(hasLoginHeader: Boolean = false) = HashMap().apply {
+ this[APPCONST.UA_NAME] = APPCONST.DEFAULT_USER_AGENT
+ getHeader()?.let {
+ GSON.fromJsonObject>(
+ when {
+ it.startsWith("@js:", true) ->
+ evalJS(it.substring(4)).toString()
+ it.startsWith("", true) ->
+ evalJS(it.substring(4, it.lastIndexOf("<"))).toString()
+ else -> it
+ }
+ )?.let { map ->
+ putAll(map)
+ }
+ }
+ if (hasLoginHeader) {
+ getLoginHeaderMap()?.let {
+ putAll(it)
+ }
+ }
+ }
+
+ /**
+ * 获取用于登录的头部信息
+ */
+ fun getLoginHeader(): String? {
+ return CacheManager.get("loginHeader_${getKey()}")
+ }
+
+ fun getLoginHeaderMap(): Map? {
+ val cache = getLoginHeader() ?: return null
+ return GSON.fromJsonObject(cache)
+ }
+
+ /**
+ * 保存登录头部信息,map格式,访问时自动添加
+ */
+ fun putLoginHeader(header: String) {
+ CacheManager.put("loginHeader_${getKey()}", header)
+ }
+
+ fun removeLoginHeader() {
+ CacheManager.delete("loginHeader_${getKey()}")
+ }
+
+ /**
+ * 获取用户信息,可以用来登录
+ * 用户信息采用aes加密存储
+ */
+ fun getLoginInfo(): String? {
+ try {
+ val key = APPCONST.androidId.encodeToByteArray(0, 8)
+ val cache = CacheManager.get("userInfo_${getKey()}") ?: return null
+ val encodeBytes = Base64.decode(cache, Base64.DEFAULT)
+ val decodeBytes = EncoderUtils.decryptAES(encodeBytes, key)
+ ?: return null
+ return String(decodeBytes)
+ } catch (e: Exception) {
+ Log.e("BaseSource","" + e.localizedMessage)
+ return null
+ }
+ }
+
+ fun getLoginInfoMap(): Map? {
+ return GSON.fromJsonObject(getLoginInfo())
+ }
+
+ /**
+ * 保存用户信息,aes加密
+ */
+ fun putLoginInfo(info: String): Boolean {
+ return try {
+ val key = (APPCONST.androidId).encodeToByteArray(0, 8)
+ val encodeBytes = EncoderUtils.encryptAES(info.toByteArray(), key)
+ val encodeStr = Base64.encodeToString(encodeBytes, Base64.DEFAULT)
+ CacheManager.put("userInfo_${getKey()}", encodeStr)
+ true
+ } catch (e: Exception) {
+ Log.e("BaseSource","" + e.localizedMessage)
+ false
+ }
+ }
+
+ fun removeLoginInfo() {
+ CacheManager.delete("userInfo_${getKey()}")
+ }
+
+ fun setVariable(variable: String?) {
+ if (variable != null) {
+ CacheManager.put("sourceVariable_${getKey()}", variable)
+ } else {
+ CacheManager.delete("sourceVariable_${getKey()}")
+ }
+ }
+
+ fun getVariable(): String? {
+ return CacheManager.get("sourceVariable_${getKey()}")
+ }
+
+ /**
+ * 执行JS
+ */
+ @Throws(Exception::class)
+ fun evalJS(jsStr: String, bindingsConfig: SimpleBindings.() -> Unit = {}): Any? {
+ val bindings = SimpleBindings()
+ bindings.apply(bindingsConfig)
+ bindings["java"] = this
+ bindings["source"] = this
+ bindings["baseUrl"] = getKey()
+ bindings["cookie"] = CookieStore
+ bindings["cache"] = CacheManager
+ return APPCONST.SCRIPT_ENGINE.eval(jsStr, bindings)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/BookType.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/BookType.kt
new file mode 100644
index 0000000..e7fc813
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/BookType.kt
@@ -0,0 +1,26 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3
+
+object BookType {
+ const val default = 0 // 0 文本
+ const val audio = 1 // 1 音频
+ const val image = 3 //图片
+ const val local = "loc_book"
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/Coroutine.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/Coroutine.kt
new file mode 100644
index 0000000..a631241
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/Coroutine.kt
@@ -0,0 +1,235 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3
+
+import android.util.Log
+import kotlinx.coroutines.*
+import kotlin.coroutines.CoroutineContext
+
+
+@Suppress("unused")
+class Coroutine(
+ val scope: CoroutineScope,
+ context: CoroutineContext = Dispatchers.IO,
+ block: suspend CoroutineScope.() -> T
+) {
+
+ companion object {
+
+ private val DEFAULT = MainScope()
+
+ fun async(
+ scope: CoroutineScope = DEFAULT,
+ context: CoroutineContext = Dispatchers.IO,
+ block: suspend CoroutineScope.() -> T
+ ): Coroutine {
+ return Coroutine(scope, context, block)
+ }
+
+ }
+
+ private val job: Job
+
+ private var start: VoidCallback? = null
+ private var success: Callback? = null
+ private var error: Callback? = null
+ private var finally: VoidCallback? = null
+ private var cancel: VoidCallback? = null
+
+ private var timeMillis: Long? = null
+ private var errorReturn: Result? = null
+
+ val isCancelled: Boolean
+ get() = job.isCancelled
+
+ val isActive: Boolean
+ get() = job.isActive
+
+ val isCompleted: Boolean
+ get() = job.isCompleted
+
+ init {
+ this.job = executeInternal(context, block)
+ }
+
+ fun timeout(timeMillis: () -> Long): Coroutine {
+ this.timeMillis = timeMillis()
+ return this@Coroutine
+ }
+
+ fun timeout(timeMillis: Long): Coroutine {
+ this.timeMillis = timeMillis
+ return this@Coroutine
+ }
+
+ fun onErrorReturn(value: () -> T?): Coroutine {
+ this.errorReturn = Result(value())
+ return this@Coroutine
+ }
+
+ fun onErrorReturn(value: T?): Coroutine {
+ this.errorReturn = Result(value)
+ return this@Coroutine
+ }
+
+ fun onStart(
+ context: CoroutineContext? = null,
+ block: (suspend CoroutineScope.() -> Unit)
+ ): Coroutine {
+ this.start = VoidCallback(context, block)
+ return this@Coroutine
+ }
+
+ fun onSuccess(
+ context: CoroutineContext? = null,
+ block: suspend CoroutineScope.(T) -> Unit
+ ): Coroutine {
+ this.success = Callback(context, block)
+ return this@Coroutine
+ }
+
+ fun onError(
+ context: CoroutineContext? = null,
+ block: suspend CoroutineScope.(Throwable) -> Unit
+ ): Coroutine {
+ this.error = Callback(context, block)
+ return this@Coroutine
+ }
+
+ fun onFinally(
+ context: CoroutineContext? = null,
+ block: suspend CoroutineScope.() -> Unit
+ ): Coroutine {
+ this.finally = VoidCallback(context, block)
+ return this@Coroutine
+ }
+
+ fun onCancel(
+ context: CoroutineContext? = null,
+ block: suspend CoroutineScope.() -> Unit
+ ): Coroutine {
+ this.cancel = VoidCallback(context, block)
+ return this@Coroutine
+ }
+
+ //取消当前任务
+ fun cancel(cause: CancellationException? = null) {
+ job.cancel(cause)
+ cancel?.let {
+ MainScope().launch {
+ if (null == it.context) {
+ it.block.invoke(scope)
+ } else {
+ withContext(scope.coroutineContext.plus(it.context)) {
+ it.block.invoke(this)
+ }
+ }
+ }
+ }
+ }
+
+ fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle {
+ return job.invokeOnCompletion(handler)
+ }
+
+ private fun executeInternal(
+ context: CoroutineContext,
+ block: suspend CoroutineScope.() -> T
+ ): Job {
+ return scope.plus(Dispatchers.Main).launch {
+ try {
+ start?.let { dispatchVoidCallback(this, it) }
+ ensureActive()
+ val value = executeBlock(scope, context, timeMillis ?: 0L, block)
+ ensureActive()
+ success?.let { dispatchCallback(this, value, it) }
+ } catch (e: CancellationException) {
+ Log.d("Coroutine", "任务取消")
+ } catch (e: Throwable) {
+ e.printStackTrace()
+ Log.d("Coroutine", "" + e.localizedMessage)
+ val consume: Boolean = errorReturn?.value?.let { value ->
+ if (isActive) {
+ success?.let { dispatchCallback(this, value, it) }
+ }
+ true
+ } ?: false
+ if (!consume && isActive) {
+ error?.let { dispatchCallback(this, e, it) }
+ }
+ } finally {
+ if (isActive) {
+ finally?.let { dispatchVoidCallback(this, it) }
+ }
+ }
+ }
+ }
+
+ private suspend inline fun dispatchVoidCallback(scope: CoroutineScope, callback: VoidCallback) {
+ if (null == callback.context) {
+ callback.block.invoke(scope)
+ } else {
+ withContext(scope.coroutineContext.plus(callback.context)) {
+ callback.block.invoke(this)
+ }
+ }
+ }
+
+ private suspend inline fun dispatchCallback(
+ scope: CoroutineScope,
+ value: R,
+ callback: Callback
+ ) {
+ if (!scope.isActive) return
+ if (null == callback.context) {
+ callback.block.invoke(scope, value)
+ } else {
+ withContext(scope.coroutineContext.plus(callback.context)) {
+ callback.block.invoke(this, value)
+ }
+ }
+ }
+
+ private suspend inline fun executeBlock(
+ scope: CoroutineScope,
+ context: CoroutineContext,
+ timeMillis: Long,
+ noinline block: suspend CoroutineScope.() -> T
+ ): T {
+ return withContext(scope.coroutineContext.plus(context)) {
+ if (timeMillis > 0L) withTimeout(timeMillis) {
+ block()
+ } else {
+ block()
+ }
+ }
+ }
+
+ private data class Result(val value: T?)
+
+ private inner class VoidCallback(
+ val context: CoroutineContext?,
+ val block: suspend CoroutineScope.() -> Unit
+ )
+
+ private inner class Callback(
+ val context: CoroutineContext?,
+ val block: suspend CoroutineScope.(VALUE) -> Unit
+ )
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/Debug.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/Debug.kt
new file mode 100644
index 0000000..8898f5a
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/Debug.kt
@@ -0,0 +1,47 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3
+
+import android.annotation.SuppressLint
+import java.text.SimpleDateFormat
+import java.util.*
+
+/**
+ * @author fengyue
+ * @date 2022/1/21 10:42
+ */
+object Debug {
+ var callback: Callback? = null
+ @SuppressLint("ConstantLocale")
+ private val debugTimeFormat = SimpleDateFormat("[hh:mm:ss.SSS]", Locale.getDefault())
+
+ fun log(msg: String) {
+ val time = debugTimeFormat.format(System.currentTimeMillis())
+ callback?.print("$time $msg")
+ }
+
+ fun log(tag: String, msg: String) {
+ val time = debugTimeFormat.format(System.currentTimeMillis())
+ callback?.print("$time $tag:$msg")
+ }
+
+ interface Callback {
+ fun print(msg: String)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/Exceptions.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/Exceptions.kt
new file mode 100644
index 0000000..10b44f1
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/Exceptions.kt
@@ -0,0 +1,67 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+@file:Suppress("unused")
+
+package xyz.fycz.myreader.model.third3
+
+class AppException(msg: String) : Exception(msg)
+
+/**
+ *
+ */
+class NoStackTraceException(msg: String) : Exception(msg) {
+
+ override fun fillInStackTrace(): Throwable {
+ return this
+ }
+
+}
+
+/**
+ * 目录为空
+ */
+class TocEmptyException(msg: String) : Exception(msg) {
+
+ override fun fillInStackTrace(): Throwable {
+ return this
+ }
+
+}
+
+/**
+ * 内容为空
+ */
+class ContentEmptyException(msg: String) : Exception(msg) {
+
+ override fun fillInStackTrace(): Throwable {
+ return this
+ }
+
+}
+
+/**
+ * 并发限制
+ */
+class ConcurrentException(msg: String, val waitTime: Int) : Exception(msg) {
+
+ override fun fillInStackTrace(): Throwable {
+ return this
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/SourceAnalyzer.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/SourceAnalyzer.kt
new file mode 100644
index 0000000..9339113
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/SourceAnalyzer.kt
@@ -0,0 +1,336 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3
+
+import android.util.Log
+import androidx.annotation.Keep
+import com.jayway.jsonpath.JsonPath
+import xyz.fycz.myreader.common.APPCONST
+import xyz.fycz.myreader.entity.thirdsource.source3.*
+import xyz.fycz.myreader.util.utils.*
+import java.util.regex.Pattern
+
+@Suppress("RegExpRedundantEscape")
+object SourceAnalyzer {
+ private val headerPattern = Pattern.compile("@Header:\\{.+?\\}", Pattern.CASE_INSENSITIVE)
+ private val jsPattern = Pattern.compile("\\{\\{.+?\\}\\}", Pattern.CASE_INSENSITIVE)
+
+ fun jsonToBookSources(json: String): List {
+ val bookSources = mutableListOf()
+ val items: List> = jsonPath.parse(json).read("$")
+ for (item in items) {
+ val jsonItem = jsonPath.parse(item)
+ jsonToBookSource(jsonItem.jsonString())?.let {
+ bookSources.add(it)
+ }
+ }
+ return bookSources
+ }
+
+ fun jsonToBookSource(json: String): Source3? {
+ val source = Source3()
+ val sourceAny = try {
+ GSON.fromJsonObject(json.trim())
+ } catch (e: Exception) {
+ null
+ }
+ try {
+ if (sourceAny?.ruleToc == null) {
+ source.apply {
+ val jsonItem = jsonPath.parse(json.trim())
+ bookSourceUrl = jsonItem.readString("bookSourceUrl") ?: return null
+ bookSourceName = jsonItem.readString("bookSourceName") ?: ""
+ bookSourceGroup = jsonItem.readString("bookSourceGroup")
+ loginUrl = jsonItem.readString("loginUrl")
+ loginUi = jsonItem.readString("loginUi")
+ loginCheckJs = jsonItem.readString("loginCheckJs")
+ bookSourceComment = jsonItem.readString("bookSourceComment") ?: ""
+ bookUrlPattern = jsonItem.readString("ruleBookUrlPattern")
+ customOrder = jsonItem.readInt("serialNumber") ?: 0
+ header = uaToHeader(jsonItem.readString("httpUserAgent"))
+ searchUrl = toNewUrl(jsonItem.readString("ruleSearchUrl"))
+ exploreUrl = toNewUrls(jsonItem.readString("ruleFindUrl"))
+ bookSourceType =
+ if (jsonItem.readString("bookSourceType") == "AUDIO") BookType.audio else BookType.default
+ enabled = jsonItem.readBool("enable") ?: true
+ if (exploreUrl.isNullOrBlank()) {
+ enabledExplore = false
+ }
+ ruleSearch = SearchRule3(
+ bookList = toNewRule(jsonItem.readString("ruleSearchList")),
+ name = toNewRule(jsonItem.readString("ruleSearchName")),
+ author = toNewRule(jsonItem.readString("ruleSearchAuthor")),
+ intro = toNewRule(jsonItem.readString("ruleSearchIntroduce")),
+ kind = toNewRule(jsonItem.readString("ruleSearchKind")),
+ bookUrl = toNewRule(jsonItem.readString("ruleSearchNoteUrl")),
+ coverUrl = toNewRule(jsonItem.readString("ruleSearchCoverUrl")),
+ lastChapter = toNewRule(jsonItem.readString("ruleSearchLastChapter"))
+ )
+ ruleExplore = ExploreRule3(
+ bookList = toNewRule(jsonItem.readString("ruleFindList")),
+ name = toNewRule(jsonItem.readString("ruleFindName")),
+ author = toNewRule(jsonItem.readString("ruleFindAuthor")),
+ intro = toNewRule(jsonItem.readString("ruleFindIntroduce")),
+ kind = toNewRule(jsonItem.readString("ruleFindKind")),
+ bookUrl = toNewRule(jsonItem.readString("ruleFindNoteUrl")),
+ coverUrl = toNewRule(jsonItem.readString("ruleFindCoverUrl")),
+ lastChapter = toNewRule(jsonItem.readString("ruleFindLastChapter"))
+ )
+ ruleBookInfo = BookInfoRule3(
+ init = toNewRule(jsonItem.readString("ruleBookInfoInit")),
+ name = toNewRule(jsonItem.readString("ruleBookName")),
+ author = toNewRule(jsonItem.readString("ruleBookAuthor")),
+ intro = toNewRule(jsonItem.readString("ruleIntroduce")),
+ kind = toNewRule(jsonItem.readString("ruleBookKind")),
+ coverUrl = toNewRule(jsonItem.readString("ruleCoverUrl")),
+ lastChapter = toNewRule(jsonItem.readString("ruleBookLastChapter")),
+ tocUrl = toNewRule(jsonItem.readString("ruleChapterUrl"))
+ )
+ ruleToc = TocRule3(
+ chapterList = toNewRule(jsonItem.readString("ruleChapterList")),
+ chapterName = toNewRule(jsonItem.readString("ruleChapterName")),
+ chapterUrl = toNewRule(jsonItem.readString("ruleContentUrl")),
+ nextTocUrl = toNewRule(jsonItem.readString("ruleChapterUrlNext"))
+ )
+ var content = toNewRule(jsonItem.readString("ruleBookContent")) ?: ""
+ if (content.startsWith("$") && !content.startsWith("$.")) {
+ content = content.substring(1)
+ }
+ ruleContent = ContentRule3(
+ content = content,
+ replaceRegex = toNewRule(jsonItem.readString("ruleBookContentReplace")),
+ nextContentUrl = toNewRule(jsonItem.readString("ruleContentUrlNext"))
+ )
+ }
+ } else {
+ source.bookSourceUrl = sourceAny.bookSourceUrl
+ source.bookSourceName = sourceAny.bookSourceName
+ source.bookSourceGroup = sourceAny.bookSourceGroup
+ source.bookSourceType = sourceAny.bookSourceType
+ source.bookUrlPattern = sourceAny.bookUrlPattern
+ source.customOrder = sourceAny.customOrder
+ source.enabled = sourceAny.enabled
+ source.enabledExplore = sourceAny.enabledExplore
+ source.concurrentRate = sourceAny.concurrentRate
+ source.header = sourceAny.header
+ source.loginUrl = when (sourceAny.loginUrl) {
+ null -> null
+ is String -> sourceAny.loginUrl.toString()
+ else -> JsonPath.parse(sourceAny.loginUrl).readString("url")
+ }
+ source.loginUi = if (sourceAny.loginUi is List<*>) {
+ GSON.toJson(sourceAny.loginUi)
+ } else {
+ sourceAny.loginUi?.toString()
+ }
+ source.loginCheckJs = sourceAny.loginCheckJs
+ source.bookSourceComment = sourceAny.bookSourceComment
+ source.lastUpdateTime = sourceAny.lastUpdateTime
+ source.respondTime = sourceAny.respondTime
+ source.weight = sourceAny.weight
+ source.exploreUrl = sourceAny.exploreUrl
+ source.ruleExplore = if (sourceAny.ruleExplore is String) {
+ GSON.fromJsonObject(sourceAny.ruleExplore.toString())
+ } else {
+ GSON.fromJsonObject(GSON.toJson(sourceAny.ruleExplore))
+ }
+ source.searchUrl = sourceAny.searchUrl
+ source.ruleSearch = if (sourceAny.ruleSearch is String) {
+ GSON.fromJsonObject(sourceAny.ruleSearch.toString())
+ } else {
+ GSON.fromJsonObject(GSON.toJson(sourceAny.ruleSearch))
+ }
+ source.ruleBookInfo = if (sourceAny.ruleBookInfo is String) {
+ GSON.fromJsonObject(sourceAny.ruleBookInfo.toString())
+ } else {
+ GSON.fromJsonObject(GSON.toJson(sourceAny.ruleBookInfo))
+ }
+ source.ruleToc = if (sourceAny.ruleToc is String) {
+ GSON.fromJsonObject(sourceAny.ruleToc.toString())
+ } else {
+ GSON.fromJsonObject(GSON.toJson(sourceAny.ruleToc))
+ }
+ source.ruleContent = if (sourceAny.ruleContent is String) {
+ GSON.fromJsonObject(sourceAny.ruleContent.toString())
+ } else {
+ GSON.fromJsonObject(GSON.toJson(sourceAny.ruleContent))
+ }
+ }
+ } catch (e: Exception) {
+ Log.e("SourceAnalyzer", "" + e.localizedMessage)
+ }
+ return source
+ }
+
+ @Keep
+ data class BookSourceAny(
+ var bookSourceName: String = "", // 名称
+ var bookSourceGroup: String? = null, // 分组
+ var bookSourceUrl: String = "", // 地址,包括 http/https
+ var bookSourceType: Int = BookType.default, // 类型,0 文本,1 音频
+ var bookUrlPattern: String? = null, // 详情页url正则
+ var customOrder: Int = 0, // 手动排序编号
+ var enabled: Boolean = true, // 是否启用
+ var enabledExplore: Boolean = true, // 启用发现
+ var concurrentRate: String? = null, // 并发率
+ var header: String? = null, // 请求头
+ var loginUrl: Any? = null, // 登录规则
+ var loginUi: Any? = null, // 登录UI
+ var loginCheckJs: String? = null, //登录检测js
+ var bookSourceComment: String? = "", //书源注释
+ var lastUpdateTime: Long = 0, // 最后更新时间,用于排序
+ var respondTime: Long = 180000L, // 响应时间,用于排序
+ var weight: Int = 0, // 智能排序的权重
+ var exploreUrl: String? = null, // 发现url
+ var ruleExplore: Any? = null, // 发现规则
+ var searchUrl: String? = null, // 搜索url
+ var ruleSearch: Any? = null, // 搜索规则
+ var ruleBookInfo: Any? = null, // 书籍信息页规则
+ var ruleToc: Any? = null, // 目录页规则
+ var ruleContent: Any? = null // 正文页规则
+ )
+
+ // default规则适配
+ // #正则#替换内容 替换成 ##正则##替换内容
+ // | 替换成 ||
+ // & 替换成 &&
+ private fun toNewRule(oldRule: String?): String? {
+ if (oldRule.isNullOrBlank()) return null
+ var newRule = oldRule
+ var reverse = false
+ var allinone = false
+ if (oldRule.startsWith("-")) {
+ reverse = true
+ newRule = oldRule.substring(1)
+ }
+ if (newRule.startsWith("+")) {
+ allinone = true
+ newRule = newRule.substring(1)
+ }
+ if (!newRule.startsWith("@CSS:", true) &&
+ !newRule.startsWith("@XPath:", true) &&
+ !newRule.startsWith("//") &&
+ !newRule.startsWith("##") &&
+ !newRule.startsWith(":") &&
+ !newRule.contains("@js:", true) &&
+ !newRule.contains("", true)
+ ) {
+ if (newRule.contains("#") && !newRule.contains("##")) {
+ newRule = oldRule.replace("#", "##")
+ }
+ if (newRule.contains("|") && !newRule.contains("||")) {
+ if (newRule.contains("##")) {
+ val list = newRule.split("##")
+ if (list[0].contains("|")) {
+ newRule = list[0].replace("|", "||")
+ for (i in 1 until list.size) {
+ newRule += "##" + list[i]
+ }
+ }
+ } else {
+ newRule = newRule.replace("|", "||")
+ }
+ }
+ if (newRule.contains("&")
+ && !newRule.contains("&&")
+ && !newRule.contains("http")
+ && !newRule.startsWith("/")
+ ) {
+ newRule = newRule.replace("&", "&&")
+ }
+ }
+ if (allinone) {
+ newRule = "+$newRule"
+ }
+ if (reverse) {
+ newRule = "-$newRule"
+ }
+ return newRule
+ }
+
+ private fun toNewUrls(oldUrls: String?): String? {
+ if (oldUrls.isNullOrBlank()) return null
+ if (oldUrls.startsWith("@js:") || oldUrls.startsWith("")) {
+ return oldUrls
+ }
+ if (!oldUrls.contains("\n") && !oldUrls.contains("&&")) {
+ return toNewUrl(oldUrls)
+ }
+ val urls = oldUrls.split("(&&|\r?\n)+".toRegex())
+ return urls.map {
+ toNewUrl(it)?.replace("\n\\s*".toRegex(), "")
+ }.joinToString("\n")
+ }
+
+ private fun toNewUrl(oldUrl: String?): String? {
+ if (oldUrl.isNullOrBlank()) return null
+ var url: String = oldUrl
+ if (oldUrl.startsWith("", true)) {
+ url = url.replace("=searchKey", "={{key}}")
+ .replace("=searchPage", "={{page}}")
+ return url
+ }
+ val map = HashMap()
+ var mather = headerPattern.matcher(url)
+ if (mather.find()) {
+ val header = mather.group()
+ url = url.replace(header, "")
+ map["headers"] = header.substring(8)
+ }
+ var urlList = url.split("|")
+ url = urlList[0]
+ if (urlList.size > 1) {
+ map["charset"] = urlList[1].split("=")[1]
+ }
+ mather = jsPattern.matcher(url)
+ val jsList = arrayListOf()
+ while (mather.find()) {
+ jsList.add(mather.group())
+ url = url.replace(jsList.last(), "$${jsList.size - 1}")
+ }
+ url = url.replace("{", "<").replace("}", ">")
+ url = url.replace("searchKey", "{{key}}")
+ url = url.replace("".toRegex(), "{{page$1}}")
+ .replace("searchPage([-+]1)".toRegex(), "{{page$1}}")
+ .replace("searchPage", "{{page}}")
+ for ((index, item) in jsList.withIndex()) {
+ url = url.replace(
+ "$$index",
+ item.replace("searchKey", "key").replace("searchPage", "page")
+ )
+ }
+ urlList = url.split("@")
+ url = urlList[0]
+ if (urlList.size > 1) {
+ map["method"] = "POST"
+ map["body"] = urlList[1]
+ }
+ if (map.size > 0) {
+ url += "," + GSON.toJson(map)
+ }
+ return url
+ }
+
+ private fun uaToHeader(ua: String?): String? {
+ if (ua.isNullOrEmpty()) return null
+ val map = mapOf(Pair(APPCONST.UA_NAME, ua))
+ return GSON.toJson(map)
+ }
+
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByJSonPath.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByJSonPath.kt
new file mode 100644
index 0000000..be78dc2
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByJSonPath.kt
@@ -0,0 +1,193 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+import android.util.Log
+import androidx.annotation.Keep
+import com.jayway.jsonpath.JsonPath
+import com.jayway.jsonpath.ReadContext
+
+import java.util.*
+
+@Suppress("RegExpRedundantEscape")
+@Keep
+class AnalyzeByJSonPath(json: Any) {
+
+ private val TAG = AnalyzeByJSonPath::class.simpleName
+
+ companion object {
+
+ fun parse(json: Any): ReadContext {
+ return when (json) {
+ is ReadContext -> json
+ is String -> JsonPath.parse(json) //JsonPath.parse(json)
+ else -> JsonPath.parse(json) //JsonPath.parse(json)
+ }
+ }
+ }
+
+ private var ctx: ReadContext = parse(json)
+
+ /**
+ * 改进解析方法
+ * 解决阅读”&&“、”||“与jsonPath支持的”&&“、”||“之间的冲突
+ * 解决{$.rule}形式规则可能匹配错误的问题,旧规则用正则解析内容含‘}’的json文本时,用规则中的字段去匹配这种内容会匹配错误.现改用平衡嵌套方法解决这个问题
+ * */
+ fun getString(rule: String): String? {
+ if (rule.isEmpty()) return null
+ var result: String
+ val ruleAnalyzes = RuleAnalyzer(rule, true) //设置平衡组为代码平衡
+ val rules = ruleAnalyzes.splitRule("&&", "||")
+
+ if (rules.size == 1) {
+
+ ruleAnalyzes.reSetPos() //将pos重置为0,复用解析器
+
+ result = ruleAnalyzes.innerRule("{$.") { getString(it) } //替换所有{$.rule...}
+
+ if (result.isEmpty()) { //st为空,表明无成功替换的内嵌规则
+ try {
+ val ob = ctx.read(rule)
+ result = if (ob is List<*>) {
+ ob.joinToString("\n")
+ } else {
+ ob.toString()
+ }
+ } catch (e: Exception) {
+ Log.e(TAG, e.toString())
+ }
+ }
+ return result
+ } else {
+ val textList = arrayListOf()
+ for (rl in rules) {
+ val temp = getString(rl)
+ if (!temp.isNullOrEmpty()) {
+ textList.add(temp)
+ if (ruleAnalyzes.elementsType == "||") {
+ break
+ }
+ }
+ }
+ return textList.joinToString("\n")
+ }
+ }
+
+ internal fun getStringList(rule: String): List {
+ val result = ArrayList()
+ if (rule.isEmpty()) return result
+ val ruleAnalyzes = RuleAnalyzer(rule, true) //设置平衡组为代码平衡
+ val rules = ruleAnalyzes.splitRule("&&", "||", "%%")
+
+ if (rules.size == 1) {
+ ruleAnalyzes.reSetPos() //将pos重置为0,复用解析器
+ val st = ruleAnalyzes.innerRule("{$.") { getString(it) } //替换所有{$.rule...}
+ if (st.isEmpty()) { //st为空,表明无成功替换的内嵌规则
+ try {
+ val obj = ctx.read(rule)
+ if (obj is List<*>) {
+ for (o in obj) result.add(o.toString())
+ } else {
+ result.add(obj.toString())
+ }
+ } catch (e: Exception) {
+ Log.e(TAG, e.toString())
+ }
+ } else {
+ result.add(st)
+ }
+ return result
+ } else {
+ val results = ArrayList>()
+ for (rl in rules) {
+ val temp = getStringList(rl)
+ if (temp.isNotEmpty()) {
+ results.add(temp)
+ if (temp.isNotEmpty() && ruleAnalyzes.elementsType == "||") {
+ break
+ }
+ }
+ }
+ if (results.size > 0) {
+ if ("%%" == ruleAnalyzes.elementsType) {
+ for (i in results[0].indices) {
+ for (temp in results) {
+ if (i < temp.size) {
+ result.add(temp[i])
+ }
+ }
+ }
+ } else {
+ for (temp in results) {
+ result.addAll(temp)
+ }
+ }
+ }
+ return result
+ }
+ }
+
+ internal fun getObject(rule: String): Any {
+ return ctx.read(rule)
+ }
+
+ internal fun getList(rule: String): ArrayList? {
+ val result = ArrayList()
+ if (rule.isEmpty()) return result
+ val ruleAnalyzes = RuleAnalyzer(rule, true) //设置平衡组为代码平衡
+ val rules = ruleAnalyzes.splitRule("&&", "||", "%%")
+ if (rules.size == 1) {
+ ctx.let {
+ try {
+ return it.read>(rules[0])
+ } catch (e: Exception) {
+ Log.e(TAG, e.toString())
+ }
+ }
+ } else {
+ val results = ArrayList>()
+ for (rl in rules) {
+ val temp = getList(rl)
+ if (temp != null && temp.isNotEmpty()) {
+ results.add(temp)
+ if (temp.isNotEmpty() && ruleAnalyzes.elementsType == "||") {
+ break
+ }
+ }
+ }
+ if (results.size > 0) {
+ if ("%%" == ruleAnalyzes.elementsType) {
+ for (i in 0 until results[0].size) {
+ for (temp in results) {
+ if (i < temp.size) {
+ temp[i]?.let { result.add(it) }
+ }
+ }
+ }
+ } else {
+ for (temp in results) {
+ result.addAll(temp)
+ }
+ }
+ }
+ }
+ return result
+ }
+
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByJSoup.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByJSoup.kt
new file mode 100644
index 0000000..ea5f432
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByJSoup.kt
@@ -0,0 +1,510 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+import androidx.annotation.Keep
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Element
+import org.jsoup.select.Collector
+import org.jsoup.select.Elements
+import org.jsoup.select.Evaluator
+import org.seimicrawler.xpath.JXNode
+
+/**
+ * Created by GKF on 2018/1/25.
+ * 书源规则解析
+ */
+@Keep
+class AnalyzeByJSoup(doc: Any) {
+ companion object {
+
+ fun parse(doc: Any): Element {
+ return when (doc) {
+ is Element -> doc
+ is JXNode -> if (doc.isElement) doc.asElement() else Jsoup.parse(doc.toString())
+ else -> Jsoup.parse(doc.toString())
+ }
+ }
+
+ }
+
+ private var element: Element = parse(doc)
+
+ /**
+ * 获取列表
+ */
+ internal fun getElements(rule: String) = getElements(element, rule)
+
+ /**
+ * 合并内容列表,得到内容
+ */
+ internal fun getString(ruleStr: String) =
+ if (ruleStr.isEmpty()) null
+ else getStringList(ruleStr).takeIf { it.isNotEmpty() }?.joinToString("\n")
+
+ /**
+ * 获取一个字符串
+ */
+ internal fun getString0(ruleStr: String) =
+ getStringList(ruleStr).let { if (it.isEmpty()) "" else it[0] }
+
+ /**
+ * 获取所有内容列表
+ */
+ internal fun getStringList(ruleStr: String): List {
+
+ val textS = ArrayList()
+
+ if (ruleStr.isEmpty()) return textS
+
+ //拆分规则
+ val sourceRule = SourceRule(ruleStr)
+
+ if (sourceRule.elementsRule.isEmpty()) {
+
+ textS.add(element.data() ?: "")
+
+ } else {
+
+ val ruleAnalyzes = RuleAnalyzer(sourceRule.elementsRule)
+ val ruleStrS = ruleAnalyzes.splitRule("&&", "||", "%%")
+
+ val results = ArrayList>()
+ for (ruleStrX in ruleStrS) {
+
+ val temp: ArrayList? =
+ if (sourceRule.isCss) {
+ val lastIndex = ruleStrX.lastIndexOf('@')
+ getResultLast(
+ element.select(ruleStrX.substring(0, lastIndex)),
+ ruleStrX.substring(lastIndex + 1)
+ )
+ } else {
+ getResultList(ruleStrX)
+ }
+
+ if (!temp.isNullOrEmpty()) {
+ results.add(temp)
+ if (ruleAnalyzes.elementsType == "||") break
+ }
+ }
+ if (results.size > 0) {
+ if ("%%" == ruleAnalyzes.elementsType) {
+ for (i in results[0].indices) {
+ for (temp in results) {
+ if (i < temp.size) {
+ textS.add(temp[i])
+ }
+ }
+ }
+ } else {
+ for (temp in results) {
+ textS.addAll(temp)
+ }
+ }
+ }
+ }
+ return textS
+ }
+
+ /**
+ * 获取Elements
+ */
+ private fun getElements(temp: Element?, rule: String): Elements {
+
+ if (temp == null || rule.isEmpty()) return Elements()
+
+ val elements = Elements()
+
+ val sourceRule = SourceRule(rule)
+ val ruleAnalyzes = RuleAnalyzer(sourceRule.elementsRule)
+ val ruleStrS = ruleAnalyzes.splitRule("&&", "||", "%%")
+
+ val elementsList = ArrayList()
+ if (sourceRule.isCss) {
+ for (ruleStr in ruleStrS) {
+ val tempS = temp.select(ruleStr)
+ elementsList.add(tempS)
+ if (tempS.size > 0 && ruleAnalyzes.elementsType == "||") {
+ break
+ }
+ }
+ } else {
+ for (ruleStr in ruleStrS) {
+
+ val rsRule = RuleAnalyzer(ruleStr)
+
+ rsRule.trim() // 修剪当前规则之前的"@"或者空白符
+
+ val rs = rsRule.splitRule("@")
+
+ val el = if (rs.size > 1) {
+ val el = Elements()
+ el.add(temp)
+ for (rl in rs) {
+ val es = Elements()
+ for (et in el) {
+ es.addAll(getElements(et, rl))
+ }
+ el.clear()
+ el.addAll(es)
+ }
+ el
+ } else ElementsSingle().getElementsSingle(temp, ruleStr)
+
+ elementsList.add(el)
+ if (el.size > 0 && ruleAnalyzes.elementsType == "||") {
+ break
+ }
+ }
+ }
+ if (elementsList.size > 0) {
+ if ("%%" == ruleAnalyzes.elementsType) {
+ for (i in 0 until elementsList[0].size) {
+ for (es in elementsList) {
+ if (i < es.size) {
+ elements.add(es[i])
+ }
+ }
+ }
+ } else {
+ for (es in elementsList) {
+ elements.addAll(es)
+ }
+ }
+ }
+ return elements
+ }
+
+ /**
+ * 获取内容列表
+ */
+ private fun getResultList(ruleStr: String): ArrayList? {
+
+ if (ruleStr.isEmpty()) return null
+
+ var elements = Elements()
+
+ elements.add(element)
+
+ val rule = RuleAnalyzer(ruleStr) //创建解析
+
+ rule.trim() //修建前置赘余符号
+
+ val rules = rule.splitRule("@") // 切割成列表
+
+ val last = rules.size - 1
+ for (i in 0 until last) {
+ val es = Elements()
+ for (elt in elements) {
+ es.addAll(ElementsSingle().getElementsSingle(elt, rules[i]))
+ }
+ elements.clear()
+ elements = es
+ }
+ return if (elements.isEmpty()) null else getResultLast(elements, rules[last])
+ }
+
+ /**
+ * 根据最后一个规则获取内容
+ */
+ private fun getResultLast(elements: Elements, lastRule: String): ArrayList {
+ val textS = ArrayList()
+ when (lastRule) {
+ "text" -> for (element in elements) {
+ val text = element.text()
+ if (text.isNotEmpty()) {
+ textS.add(text)
+ }
+ }
+ "textNodes" -> for (element in elements) {
+ val tn = arrayListOf()
+ val contentEs = element.textNodes()
+ for (item in contentEs) {
+ val text = item.text().trim { it <= ' ' }
+ if (text.isNotEmpty()) {
+ tn.add(text)
+ }
+ }
+ if (tn.isNotEmpty()) {
+ textS.add(tn.joinToString("\n"))
+ }
+ }
+ "ownText" -> for (element in elements) {
+ val text = element.ownText()
+ if (text.isNotEmpty()) {
+ textS.add(text)
+ }
+ }
+ "html" -> {
+ elements.select("script").remove()
+ elements.select("style").remove()
+ val html = elements.outerHtml()
+ if (html.isNotEmpty()) {
+ textS.add(html)
+ }
+ }
+ "all" -> textS.add(elements.outerHtml())
+ else -> for (element in elements) {
+
+ val url = element.attr(lastRule)
+
+ if (url.isBlank() || textS.contains(url)) continue
+
+ textS.add(url)
+ }
+ }
+ return textS
+ }
+
+ /**
+ * 1.支持阅读原有写法,':'分隔索引,!或.表示筛选方式,索引可为负数
+ * 例如 tag.div.-1:10:2 或 tag.div!0:3
+ *
+ * 2. 支持与jsonPath类似的[]索引写法
+ * 格式形如 [it,it,。。。] 或 [!it,it,。。。] 其中[!开头表示筛选方式为排除,it为单个索引或区间。
+ * 区间格式为 start:end 或 start:end:step,其中start为0可省略,end为-1可省略。
+ * 索引,区间两端及间隔都支持负数
+ * 例如 tag.div[-1, 3:-2:-10, 2]
+ * 特殊用法 tag.div[-1:0] 可在任意地方让列表反向
+ * */
+ @Suppress("UNCHECKED_CAST")
+ data class ElementsSingle(
+ var split: Char = '.',
+ var beforeRule: String = "",
+ val indexDefault: MutableList = mutableListOf(),
+ val indexes: MutableList = mutableListOf()
+ ) {
+ /**
+ * 获取Elements按照一个规则
+ */
+ fun getElementsSingle(temp: Element, rule: String): Elements {
+
+ findIndexSet(rule) //执行索引列表处理器
+
+ /**
+ * 获取所有元素
+ * */
+ var elements =
+ if (beforeRule.isEmpty()) temp.children() //允许索引直接作为根元素,此时前置规则为空,效果与children相同
+ else {
+ val rules = beforeRule.split(".")
+ when (rules[0]) {
+ "children" -> temp.children() //允许索引直接作为根元素,此时前置规则为空,效果与children相同
+ "class" -> temp.getElementsByClass(rules[1])
+ "tag" -> temp.getElementsByTag(rules[1])
+ "id" -> Collector.collect(Evaluator.Id(rules[1]), temp)
+ "text" -> temp.getElementsContainingOwnText(rules[1])
+ else -> temp.select(beforeRule)
+ }
+ }
+
+ val len = elements.size
+ val lastIndexes = (indexDefault.size - 1).takeIf { it != -1 } ?: indexes.size - 1
+ val indexSet = mutableSetOf()
+
+ /**
+ * 获取无重且不越界的索引集合
+ * */
+ if (indexes.isEmpty()) for (ix in lastIndexes downTo 0) { //indexes为空,表明是非[]式索引,集合是逆向遍历插入的,所以这里也逆向遍历,好还原顺序
+
+ val it = indexDefault[ix]
+ if (it in 0 until len) indexSet.add(it) //将正数不越界的索引添加到集合
+ else if (it < 0 && len >= -it) indexSet.add(it + len) //将负数不越界的索引添加到集合
+
+ } else for (ix in lastIndexes downTo 0) { //indexes不空,表明是[]式索引,集合是逆向遍历插入的,所以这里也逆向遍历,好还原顺序
+
+ if (indexes[ix] is Triple<*, *, *>) { //区间
+ val (startX, endX, stepX) = indexes[ix] as Triple //还原储存时的类型
+
+ val start = if (startX == null) 0 //左端省略表示0
+ else if (startX >= 0) if (startX < len) startX else len - 1 //右端越界,设置为最大索引
+ else if (-startX <= len) len + startX /* 将负索引转正 */ else 0 //左端越界,设置为最小索引
+
+ val end = if (endX == null) len - 1 //右端省略表示 len - 1
+ else if (endX >= 0) if (endX < len) endX else len - 1 //右端越界,设置为最大索引
+ else if (-endX <= len) len + endX /* 将负索引转正 */ else 0 //左端越界,设置为最小索引
+
+ if (start == end || stepX >= len) { //两端相同,区间里只有一个数。或间隔过大,区间实际上仅有首位
+
+ indexSet.add(start)
+ continue
+
+ }
+
+ val step =
+ if (stepX > 0) stepX else if (-stepX < len) stepX + len else 1 //最小正数间隔为1
+
+ //将区间展开到集合中,允许列表反向。
+ indexSet.addAll(if (end > start) start..end step step else start downTo end step step)
+
+ } else {//单个索引
+
+ val it = indexes[ix] as Int //还原储存时的类型
+
+ if (it in 0 until len) indexSet.add(it) //将正数不越界的索引添加到集合
+ else if (it < 0 && len >= -it) indexSet.add(it + len) //将负数不越界的索引添加到集合
+
+ }
+
+ }
+
+ /**
+ * 根据索引集合筛选元素
+ * */
+ if (split == '!') { //排除
+
+ for (pcInt in indexSet) elements[pcInt] = null
+
+ elements.removeAll(listOf(null)) //测试过,这样就行
+
+ } else if (split == '.') { //选择
+
+ val es = Elements()
+
+ for (pcInt in indexSet) es.add(elements[pcInt])
+
+ elements = es
+
+ }
+
+ return elements //返回筛选结果
+
+ }
+
+ private fun findIndexSet(rule: String) {
+
+ val rus = rule.trim { it <= ' ' }
+
+ var len = rus.length
+ var curInt: Int? //当前数字
+ var curMinus = false //当前数字是否为负
+ val curList = mutableListOf() //当前数字区间
+ var l = "" //暂存数字字符串
+
+ val head = rus.last() == ']' //是否为常规索引写法
+
+ if (head) { //常规索引写法[index...]
+
+ len-- //跳过尾部']'
+
+ while (len-- >= 0) { //逆向遍历,可以无前置规则
+
+ var rl = rus[len]
+ if (rl == ' ') continue //跳过空格
+
+ if (rl in '0'..'9') l = rl + l //将数值累接入临时字串中,遇到分界符才取出
+ else if (rl == '-') curMinus = true
+ else {
+
+ curInt =
+ if (l.isEmpty()) null else if (curMinus) -l.toInt() else l.toInt() //当前数字
+
+ when (rl) {
+
+ ':' -> curList.add(curInt) //区间右端或区间间隔
+
+ else -> {
+
+ //为保证查找顺序,区间和单个索引都添加到同一集合
+ if (curList.isEmpty()) {
+
+ if (curInt == null) break //是jsoup选择器而非索引列表,跳出
+
+ indexes.add(curInt)
+ } else {
+
+ //列表最后压入的是区间右端,若列表有两位则最先压入的是间隔
+ indexes.add(
+ Triple(
+ curInt,
+ curList.last(),
+ if (curList.size == 2) curList.first() else 1
+ )
+ )
+
+ curList.clear() //重置临时列表,避免影响到下个区间的处理
+
+ }
+
+ if (rl == '!') {
+ split = '!'
+ do {
+ rl = rus[--len]
+ } while (len > 0 && rl == ' ')//跳过所有空格
+ }
+
+ if (rl == '[') {
+ beforeRule = rus.substring(0, len) //遇到索引边界,返回结果
+ return
+ }
+
+ if (rl != ',') break //非索引结构,跳出
+
+ }
+ }
+
+ l = "" //清空
+ curMinus = false //重置
+ }
+ }
+ } else while (len-- >= 0) { //阅读原本写法,逆向遍历,可以无前置规则
+
+ val rl = rus[len]
+ if (rl == ' ') continue //跳过空格
+
+ if (rl in '0'..'9') l = rl + l //将数值累接入临时字串中,遇到分界符才取出
+ else if (rl == '-') curMinus = true
+ else {
+
+ if (rl == '!' || rl == '.' || rl == ':') { //分隔符或起始符
+
+ indexDefault.add(if (curMinus) -l.toInt() else l.toInt()) // 当前数字追加到列表
+
+ if (rl != ':') { //rl == '!' || rl == '.'
+ split = rl
+ beforeRule = rus.substring(0, len)
+ return
+ }
+
+ } else break //非索引结构,跳出循环
+
+ l = "" //清空
+ curMinus = false //重置
+ }
+
+ }
+
+ split = ' '
+ beforeRule = rus
+ }
+ }
+
+
+ internal inner class SourceRule(ruleStr: String) {
+ var isCss = false
+ var elementsRule: String = if (ruleStr.startsWith("@CSS:", true)) {
+ isCss = true
+ ruleStr.substring(5).trim { it <= ' ' }
+ } else {
+ ruleStr
+ }
+ }
+
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByRegex.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByRegex.kt
new file mode 100644
index 0000000..2518f21
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByRegex.kt
@@ -0,0 +1,79 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+import androidx.annotation.Keep
+import java.util.*
+import java.util.regex.Pattern
+
+@Keep
+object AnalyzeByRegex {
+
+ fun getElement(res: String, regs: Array, index: Int = 0): List? {
+ var vIndex = index
+ val resM = Pattern.compile(regs[vIndex]).matcher(res)
+ if (!resM.find()) {
+ return null
+ }
+ // 判断索引的规则是最后一个规则
+ return if (vIndex + 1 == regs.size) {
+ // 新建容器
+ val info = arrayListOf()
+ for (groupIndex in 0..resM.groupCount()) {
+ info.add(resM.group(groupIndex)!!)
+ }
+ info
+ } else {
+ val result = StringBuilder()
+ do {
+ result.append(resM.group())
+ } while (resM.find())
+ getElement(result.toString(), regs, ++vIndex)
+ }
+ }
+
+ fun getElements(res: String, regs: Array, index: Int = 0): List> {
+ var vIndex = index
+ val resM = Pattern.compile(regs[vIndex]).matcher(res)
+ if (!resM.find()) {
+ return arrayListOf()
+ }
+ // 判断索引的规则是最后一个规则
+ if (vIndex + 1 == regs.size) {
+ // 创建书息缓存数组
+ val books = ArrayList>()
+ // 提取列表
+ do {
+ // 新建容器
+ val info = arrayListOf()
+ for (groupIndex in 0..resM.groupCount()) {
+ info.add(resM.group(groupIndex)!!)
+ }
+ books.add(info)
+ } while (resM.find())
+ return books
+ } else {
+ val result = StringBuilder()
+ do {
+ result.append(resM.group())
+ } while (resM.find())
+ return getElements(result.toString(), regs, ++vIndex)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByXPath.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByXPath.kt
new file mode 100644
index 0000000..ba2e54d
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeByXPath.kt
@@ -0,0 +1,167 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+import android.text.TextUtils
+import androidx.annotation.Keep
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+import org.jsoup.select.Elements
+import org.seimicrawler.xpath.JXDocument
+import org.seimicrawler.xpath.JXNode
+import java.util.*
+
+@Keep
+class AnalyzeByXPath(doc: Any) {
+ private var jxNode: Any = parse(doc)
+
+ private fun parse(doc: Any): Any {
+ return when (doc) {
+ is JXNode -> if (doc.isElement) doc else strToJXDocument(doc.toString())
+ is Document -> JXDocument.create(doc)
+ is Element -> JXDocument.create(Elements(doc))
+ is Elements -> JXDocument.create(doc)
+ else -> strToJXDocument(doc.toString())
+ }
+ }
+
+ private fun strToJXDocument(html: String): JXDocument {
+ var html1 = html
+ if (html1.endsWith("")) {
+ html1 = "${html1} "
+ }
+ if (html1.endsWith("") || html1.endsWith("")) {
+ html1 = ""
+ }
+ return JXDocument.create(html1)
+ }
+
+ private fun getResult(xPath: String): List? {
+ val node = jxNode
+ return if (node is JXNode) {
+ node.sel(xPath)
+ } else {
+ (node as JXDocument).selN(xPath)
+ }
+ }
+
+ internal fun getElements(xPath: String): List? {
+
+ if (xPath.isEmpty()) return null
+
+ val jxNodes = ArrayList()
+ val ruleAnalyzes = RuleAnalyzer(xPath)
+ val rules = ruleAnalyzes.splitRule("&&", "||", "%%")
+
+ if (rules.size == 1) {
+ return getResult(rules[0])
+ } else {
+ val results = ArrayList>()
+ for (rl in rules) {
+ val temp = getElements(rl)
+ if (temp != null && temp.isNotEmpty()) {
+ results.add(temp)
+ if (temp.isNotEmpty() && ruleAnalyzes.elementsType == "||") {
+ break
+ }
+ }
+ }
+ if (results.size > 0) {
+ if ("%%" == ruleAnalyzes.elementsType) {
+ for (i in results[0].indices) {
+ for (temp in results) {
+ if (i < temp.size) {
+ jxNodes.add(temp[i])
+ }
+ }
+ }
+ } else {
+ for (temp in results) {
+ jxNodes.addAll(temp)
+ }
+ }
+ }
+ }
+ return jxNodes
+ }
+
+ internal fun getStringList(xPath: String): List {
+
+ val result = ArrayList()
+ val ruleAnalyzes = RuleAnalyzer(xPath)
+ val rules = ruleAnalyzes.splitRule("&&", "||", "%%")
+
+ if (rules.size == 1) {
+ getResult(xPath)?.map {
+ result.add(it.asString())
+ }
+ return result
+ } else {
+ val results = ArrayList>()
+ for (rl in rules) {
+ val temp = getStringList(rl)
+ if (temp.isNotEmpty()) {
+ results.add(temp)
+ if (temp.isNotEmpty() && ruleAnalyzes.elementsType == "||") {
+ break
+ }
+ }
+ }
+ if (results.size > 0) {
+ if ("%%" == ruleAnalyzes.elementsType) {
+ for (i in results[0].indices) {
+ for (temp in results) {
+ if (i < temp.size) {
+ result.add(temp[i])
+ }
+ }
+ }
+ } else {
+ for (temp in results) {
+ result.addAll(temp)
+ }
+ }
+ }
+ }
+ return result
+ }
+
+ fun getString(rule: String): String? {
+ val ruleAnalyzes = RuleAnalyzer(rule)
+ val rules = ruleAnalyzes.splitRule("&&", "||")
+ if (rules.size == 1) {
+ getResult(rule)?.let {
+ return TextUtils.join("\n", it)
+ }
+ return null
+ } else {
+ val textList = arrayListOf()
+ for (rl in rules) {
+ val temp = getString(rl)
+ if (!temp.isNullOrEmpty()) {
+ textList.add(temp)
+ if (ruleAnalyzes.elementsType == "||") {
+ break
+ }
+ }
+ }
+ return textList.joinToString("\n")
+ }
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeRule.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeRule.kt
new file mode 100644
index 0000000..6432378
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeRule.kt
@@ -0,0 +1,712 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+import android.text.TextUtils
+import android.util.Log
+import androidx.annotation.Keep
+import kotlinx.coroutines.runBlocking
+import org.jsoup.nodes.Entities
+import org.mozilla.javascript.NativeObject
+import xyz.fycz.myreader.common.APPCONST.JS_PATTERN_3
+import xyz.fycz.myreader.common.APPCONST.SCRIPT_ENGINE
+import xyz.fycz.myreader.greendao.entity.Book
+import xyz.fycz.myreader.greendao.entity.Chapter
+import xyz.fycz.myreader.greendao.service.CacheManager
+import xyz.fycz.myreader.greendao.service.CookieStore
+import xyz.fycz.myreader.model.third3.BaseSource
+import xyz.fycz.myreader.util.utils.*
+import java.net.URL
+import java.util.*
+import java.util.regex.Pattern
+import javax.script.SimpleBindings
+import kotlin.collections.HashMap
+
+/**
+ * 解析规则获取结果
+ */
+@Keep
+@Suppress("unused", "RegExpRedundantEscape", "MemberVisibilityCanBePrivate")
+class AnalyzeRule(
+ val ruleData: RuleDataInterface,
+ private val source: BaseSource? = null
+) : JsExtensions {
+
+ var book = if (ruleData is Book) ruleData else null
+
+ var chapter: Chapter? = null
+ var nextChapterUrl: String? = null
+ var content: Any? = null
+ private set
+ var baseUrl: String? = null
+ private set
+ var redirectUrl: URL? = null
+ private set
+ private var isJSON: Boolean = false
+ private var isRegex: Boolean = false
+
+ private var analyzeByXPath: AnalyzeByXPath? = null
+ private var analyzeByJSoup: AnalyzeByJSoup? = null
+ private var analyzeByJSonPath: AnalyzeByJSonPath? = null
+
+ private var objectChangedXP = false
+ private var objectChangedJS = false
+ private var objectChangedJP = false
+
+ @JvmOverloads
+ fun setContent(content: Any?, baseUrl: String? = null): AnalyzeRule {
+ if (content == null) throw AssertionError("内容不可空(Content cannot be null)")
+ this.content = content
+ isJSON = content.toString().isJson()
+ setBaseUrl(baseUrl)
+ objectChangedXP = true
+ objectChangedJS = true
+ objectChangedJP = true
+ return this
+ }
+
+ fun setBaseUrl(baseUrl: String?): AnalyzeRule {
+ baseUrl?.let {
+ this.baseUrl = baseUrl
+ }
+ return this
+ }
+
+ fun setRedirectUrl(url: String): URL? {
+ try {
+ redirectUrl = URL(url)
+ } catch (e: Exception) {
+ log("URL($url) error\n${e.localizedMessage}")
+ }
+ return redirectUrl
+ }
+
+ /**
+ * 获取XPath解析类
+ */
+ private fun getAnalyzeByXPath(o: Any): AnalyzeByXPath {
+ return if (o != content) {
+ AnalyzeByXPath(o)
+ } else {
+ if (analyzeByXPath == null || objectChangedXP) {
+ analyzeByXPath = AnalyzeByXPath(content!!)
+ objectChangedXP = false
+ }
+ analyzeByXPath!!
+ }
+ }
+
+ /**
+ * 获取JSOUP解析类
+ */
+ private fun getAnalyzeByJSoup(o: Any): AnalyzeByJSoup {
+ return if (o != content) {
+ AnalyzeByJSoup(o)
+ } else {
+ if (analyzeByJSoup == null || objectChangedJS) {
+ analyzeByJSoup = AnalyzeByJSoup(content!!)
+ objectChangedJS = false
+ }
+ analyzeByJSoup!!
+ }
+ }
+
+ /**
+ * 获取JSON解析类
+ */
+ private fun getAnalyzeByJSonPath(o: Any): AnalyzeByJSonPath {
+ return if (o != content) {
+ AnalyzeByJSonPath(o)
+ } else {
+ if (analyzeByJSonPath == null || objectChangedJP) {
+ analyzeByJSonPath = AnalyzeByJSonPath(content!!)
+ objectChangedJP = false
+ }
+ analyzeByJSonPath!!
+ }
+ }
+
+ /**
+ * 获取文本列表
+ */
+ @JvmOverloads
+ fun getStringList(rule: String?, mContent: Any? = null, isUrl: Boolean = false): List? {
+ if (rule.isNullOrEmpty()) return null
+ val ruleList = splitSourceRule(rule, false)
+ return getStringList(ruleList, mContent, isUrl)
+ }
+
+ @JvmOverloads
+ fun getStringList(
+ ruleList: List,
+ mContent: Any? = null,
+ isUrl: Boolean = false
+ ): List? {
+ var result: Any? = null
+ val content = mContent ?: this.content
+ if (content != null && ruleList.isNotEmpty()) {
+ result = content
+ if (content is NativeObject) {
+ result = content[ruleList[0].rule]?.toString()
+ } else {
+ for (sourceRule in ruleList) {
+ putRule(sourceRule.putMap)
+ sourceRule.makeUpRule(result)
+ result?.let {
+ if (sourceRule.rule.isNotEmpty()) {
+ result = when (sourceRule.mode) {
+ Mode.Js -> evalJS(sourceRule.rule, result)
+ Mode.Json -> getAnalyzeByJSonPath(it).getStringList(sourceRule.rule)
+ Mode.XPath -> getAnalyzeByXPath(it).getStringList(sourceRule.rule)
+ Mode.Default -> getAnalyzeByJSoup(it).getStringList(sourceRule.rule)
+ else -> sourceRule.rule
+ }
+ }
+ if (sourceRule.replaceRegex.isNotEmpty() && result is List<*>) {
+ val newList = ArrayList()
+ for (item in result as List<*>) {
+ newList.add(replaceRegex(item.toString(), sourceRule))
+ }
+ result = newList
+ } else if (sourceRule.replaceRegex.isNotEmpty()) {
+ result = replaceRegex(result.toString(), sourceRule)
+ }
+ }
+ }
+ }
+ }
+ if (result == null) return null
+ if (result is String) {
+ result = (result as String).split("\n")
+ }
+ if (isUrl) {
+ val urlList = ArrayList()
+ if (result is List<*>) {
+ for (url in result as List<*>) {
+ val absoluteURL = NetworkUtils.getAbsoluteURL(redirectUrl, url.toString())
+ if (absoluteURL.isNotEmpty() && !urlList.contains(absoluteURL)) {
+ urlList.add(absoluteURL)
+ }
+ }
+ }
+ return urlList
+ }
+ @Suppress("UNCHECKED_CAST")
+ return result as? List
+ }
+
+ /**
+ * 获取文本
+ */
+ @JvmOverloads
+ fun getString(ruleStr: String?, mContent: Any? = null, isUrl: Boolean = false): String {
+ if (TextUtils.isEmpty(ruleStr)) return ""
+ val ruleList = splitSourceRule(ruleStr)
+ return getString(ruleList, mContent, isUrl)
+ }
+
+ @JvmOverloads
+ fun getString(
+ ruleList: List,
+ mContent: Any? = null,
+ isUrl: Boolean = false
+ ): String {
+ var result: Any? = null
+ val content = mContent ?: this.content
+ if (content != null && ruleList.isNotEmpty()) {
+ result = content
+ if (result is NativeObject) {
+ result = result[ruleList[0].rule]?.toString()
+ } else {
+ for (sourceRule in ruleList) {
+ putRule(sourceRule.putMap)
+ sourceRule.makeUpRule(result)
+ result?.let {
+ if (sourceRule.rule.isNotBlank() || sourceRule.replaceRegex.isEmpty()) {
+ result = when (sourceRule.mode) {
+ Mode.Js -> evalJS(sourceRule.rule, it)
+ Mode.Json -> getAnalyzeByJSonPath(it).getString(sourceRule.rule)
+ Mode.XPath -> getAnalyzeByXPath(it).getString(sourceRule.rule)
+ Mode.Default -> if (isUrl) {
+ getAnalyzeByJSoup(it).getString0(sourceRule.rule)
+ } else {
+ getAnalyzeByJSoup(it).getString(sourceRule.rule)
+ }
+ else -> sourceRule.rule
+ }
+ }
+ if ((result != null) && sourceRule.replaceRegex.isNotEmpty()) {
+ result = replaceRegex(result.toString(), sourceRule)
+ }
+ }
+ }
+ }
+ }
+ if (result == null) result = ""
+ val str = kotlin.runCatching {
+ Entities.unescape(result.toString())
+ }.onFailure {
+ log("Entities.unescape() error\n${it.localizedMessage}")
+ }.getOrElse {
+ result.toString()
+ }
+ if (isUrl) {
+ return if (str.isBlank()) {
+ baseUrl ?: ""
+ } else {
+ NetworkUtils.getAbsoluteURL(redirectUrl, str)
+ }
+ }
+ return str
+ }
+
+ /**
+ * 获取Element
+ */
+ fun getElement(ruleStr: String): Any? {
+ if (TextUtils.isEmpty(ruleStr)) return null
+ var result: Any? = null
+ val content = this.content
+ val ruleList = splitSourceRule(ruleStr, true)
+ if (content != null && ruleList.isNotEmpty()) {
+ result = content
+ for (sourceRule in ruleList) {
+ putRule(sourceRule.putMap)
+ sourceRule.makeUpRule(result)
+ result?.let {
+ result = when (sourceRule.mode) {
+ Mode.Regex -> AnalyzeByRegex.getElement(
+ result.toString(),
+ sourceRule.rule.splitNotBlank("&&")
+ )
+ Mode.Js -> evalJS(sourceRule.rule, it)
+ Mode.Json -> getAnalyzeByJSonPath(it).getObject(sourceRule.rule)
+ Mode.XPath -> getAnalyzeByXPath(it).getElements(sourceRule.rule)
+ else -> getAnalyzeByJSoup(it).getElements(sourceRule.rule)
+ }
+ if (sourceRule.replaceRegex.isNotEmpty()) {
+ result = replaceRegex(result.toString(), sourceRule)
+ }
+ }
+ }
+ }
+ return result
+ }
+
+ /**
+ * 获取列表
+ */
+ @Suppress("UNCHECKED_CAST")
+ fun getElements(ruleStr: String): List {
+ var result: Any? = null
+ val content = this.content
+ val ruleList = splitSourceRule(ruleStr, true)
+ if (content != null && ruleList.isNotEmpty()) {
+ result = content
+ for (sourceRule in ruleList) {
+ putRule(sourceRule.putMap)
+ result?.let {
+ result = when (sourceRule.mode) {
+ Mode.Regex -> AnalyzeByRegex.getElements(
+ result.toString(),
+ sourceRule.rule.splitNotBlank("&&")
+ )
+ Mode.Js -> evalJS(sourceRule.rule, result)
+ Mode.Json -> getAnalyzeByJSonPath(it).getList(sourceRule.rule)
+ Mode.XPath -> getAnalyzeByXPath(it).getElements(sourceRule.rule)
+ else -> getAnalyzeByJSoup(it).getElements(sourceRule.rule)
+ }
+ if (sourceRule.replaceRegex.isNotEmpty()) {
+ result = replaceRegex(result.toString(), sourceRule)
+ }
+ }
+ }
+ }
+ result?.let {
+ return it as List
+ }
+ return ArrayList()
+ }
+
+ /**
+ * 保存变量
+ */
+ private fun putRule(map: Map) {
+ for ((key, value) in map) {
+ put(key, getString(value))
+ }
+ }
+
+ /**
+ * 分离put规则
+ */
+ private fun splitPutRule(ruleStr: String, putMap: HashMap): String {
+ var vRuleStr = ruleStr
+ val putMatcher = putPattern.matcher(vRuleStr)
+ while (putMatcher.find()) {
+ vRuleStr = vRuleStr.replace(putMatcher.group(), "")
+ val map = GSON.fromJsonObject>(putMatcher.group(1))
+ map?.let { putMap.putAll(map) }
+ }
+ return vRuleStr
+ }
+
+ /**
+ * 正则替换
+ */
+ private fun replaceRegex(result: String, rule: SourceRule): String {
+ if (rule.replaceRegex.isEmpty()) return result
+ var vResult = result
+ vResult = if (rule.replaceFirst) {
+ kotlin.runCatching {
+ val pattern = Pattern.compile(rule.replaceRegex)
+ val matcher = pattern.matcher(vResult)
+ if (matcher.find()) {
+ matcher.group(0)!!.replaceFirst(rule.replaceRegex.toRegex(), rule.replacement)
+ } else {
+ ""
+ }
+ }.getOrElse {
+ vResult.replaceFirst(rule.replaceRegex, rule.replacement)
+ }
+ } else {
+ kotlin.runCatching {
+ vResult.replace(rule.replaceRegex.toRegex(), rule.replacement)
+ }.getOrElse {
+ vResult.replace(rule.replaceRegex, rule.replacement)
+ }
+ }
+ return vResult
+ }
+
+ /**
+ * 分解规则生成规则列表
+ */
+ fun splitSourceRule(ruleStr: String?, allInOne: Boolean = false): List {
+ if (ruleStr.isNullOrEmpty()) return ArrayList()
+ val ruleList = ArrayList()
+ var mMode: Mode = Mode.Default
+ var start = 0
+ //仅首字符为:时为AllInOne,其实:与伪类选择器冲突,建议改成?更合理
+ if (allInOne && ruleStr.startsWith(":")) {
+ mMode = Mode.Regex
+ isRegex = true
+ start = 1
+ } else if (isRegex) {
+ mMode = Mode.Regex
+ }
+ var tmp: String
+ val jsMatcher = JS_PATTERN_3.matcher(ruleStr)
+ while (jsMatcher.find()) {
+ if (jsMatcher.start() > start) {
+ tmp = ruleStr.substring(start, jsMatcher.start()).trim { it <= ' ' }
+ if (tmp.isNotEmpty()) {
+ ruleList.add(SourceRule(tmp, mMode))
+ }
+ }
+ ruleList.add(SourceRule(jsMatcher.group(2) ?: jsMatcher.group(1), Mode.Js))
+ start = jsMatcher.end()
+ }
+
+ if (ruleStr.length > start) {
+ tmp = ruleStr.substring(start).trim { it <= ' ' }
+ if (tmp.isNotEmpty()) {
+ ruleList.add(SourceRule(tmp, mMode))
+ }
+ }
+
+ return ruleList
+ }
+
+ /**
+ * 规则类
+ */
+ inner class SourceRule internal constructor(
+ ruleStr: String,
+ internal var mode: Mode = Mode.Default
+ ) {
+ internal var rule: String
+ internal var replaceRegex = ""
+ internal var replacement = ""
+ internal var replaceFirst = false
+ internal val putMap = HashMap()
+ private val ruleParam = ArrayList()
+ private val ruleType = ArrayList()
+ private val getRuleType = -2
+ private val jsRuleType = -1
+ private val defaultRuleType = 0
+
+ init {
+ rule = when {
+ mode == Mode.Js || mode == Mode.Regex -> ruleStr
+ ruleStr.startsWith("@CSS:", true) -> {
+ mode = Mode.Default
+ ruleStr
+ }
+ ruleStr.startsWith("@@") -> {
+ mode = Mode.Default
+ ruleStr.substring(2)
+ }
+ ruleStr.startsWith("@XPath:", true) -> {
+ mode = Mode.XPath
+ ruleStr.substring(7)
+ }
+ ruleStr.startsWith("@Json:", true) -> {
+ mode = Mode.Json
+ ruleStr.substring(6)
+ }
+ isJSON || ruleStr.startsWith("$.") || ruleStr.startsWith("$[") -> {
+ mode = Mode.Json
+ ruleStr
+ }
+ ruleStr.startsWith("/") -> {//XPath特征很明显,无需配置单独的识别标头
+ mode = Mode.XPath
+ ruleStr
+ }
+ else -> ruleStr
+ }
+ //分离put
+ rule = splitPutRule(rule, putMap)
+ //@get,{{ }}, 拆分
+ var start = 0
+ var tmp: String
+ val evalMatcher = evalPattern.matcher(rule)
+
+ if (evalMatcher.find()) {
+ tmp = rule.substring(start, evalMatcher.start())
+ if (mode != Mode.Js && mode != Mode.Regex &&
+ (evalMatcher.start() == 0 || !tmp.contains("##"))
+ ) {
+ mode = Mode.Regex
+ }
+ do {
+ if (evalMatcher.start() > start) {
+ tmp = rule.substring(start, evalMatcher.start())
+ splitRegex(tmp)
+ }
+ tmp = evalMatcher.group()
+ when {
+ tmp.startsWith("@get:", true) -> {
+ ruleType.add(getRuleType)
+ ruleParam.add(tmp.substring(6, tmp.lastIndex))
+ }
+ tmp.startsWith("{{") -> {
+ ruleType.add(jsRuleType)
+ ruleParam.add(tmp.substring(2, tmp.length - 2))
+ }
+ else -> {
+ splitRegex(tmp)
+ }
+ }
+ start = evalMatcher.end()
+ } while (evalMatcher.find())
+ }
+ if (rule.length > start) {
+ tmp = rule.substring(start)
+ splitRegex(tmp)
+ }
+ }
+
+ /**
+ * 拆分\$\d{1,2}
+ */
+ private fun splitRegex(ruleStr: String) {
+ var start = 0
+ var tmp: String
+ val ruleStrArray = ruleStr.split("##")
+ val regexMatcher = regexPattern.matcher(ruleStrArray[0])
+
+ if (regexMatcher.find()) {
+ if (mode != Mode.Js && mode != Mode.Regex) {
+ mode = Mode.Regex
+ }
+ do {
+ if (regexMatcher.start() > start) {
+ tmp = ruleStr.substring(start, regexMatcher.start())
+ ruleType.add(defaultRuleType)
+ ruleParam.add(tmp)
+ }
+ tmp = regexMatcher.group()
+ ruleType.add(tmp.substring(1).toInt())
+ ruleParam.add(tmp)
+ start = regexMatcher.end()
+ } while (regexMatcher.find())
+ }
+ if (ruleStr.length > start) {
+ tmp = ruleStr.substring(start)
+ ruleType.add(defaultRuleType)
+ ruleParam.add(tmp)
+ }
+ }
+
+ /**
+ * 替换@get,{{ }}
+ */
+ fun makeUpRule(result: Any?) {
+ val infoVal = StringBuilder()
+ if (ruleParam.isNotEmpty()) {
+ var index = ruleParam.size
+ while (index-- > 0) {
+ val regType = ruleType[index]
+ when {
+ regType > defaultRuleType -> {
+ @Suppress("UNCHECKED_CAST")
+ (result as? List)?.run {
+ if (this.size > regType) {
+ this[regType]?.let {
+ infoVal.insert(0, it)
+ }
+ }
+ } ?: infoVal.insert(0, ruleParam[index])
+ }
+ regType == jsRuleType -> {
+ if (isRule(ruleParam[index])) {
+ getString(arrayListOf(SourceRule(ruleParam[index]))).let {
+ infoVal.insert(0, it)
+ }
+ } else {
+ val jsEval: Any? = evalJS(ruleParam[index], result)
+ when {
+ jsEval == null -> Unit
+ jsEval is String -> infoVal.insert(0, jsEval)
+ jsEval is Double && jsEval % 1.0 == 0.0 -> infoVal.insert(
+ 0,
+ String.format("%.0f", jsEval)
+ )
+ else -> infoVal.insert(0, jsEval.toString())
+ }
+ }
+ }
+ regType == getRuleType -> {
+ infoVal.insert(0, get(ruleParam[index]))
+ }
+ else -> infoVal.insert(0, ruleParam[index])
+ }
+ }
+ rule = infoVal.toString()
+ }
+ //分离正则表达式
+ val ruleStrS = rule.split("##")
+ rule = ruleStrS[0].trim()
+ if (ruleStrS.size > 1) {
+ replaceRegex = ruleStrS[1]
+ }
+ if (ruleStrS.size > 2) {
+ replacement = ruleStrS[2]
+ }
+ if (ruleStrS.size > 3) {
+ replaceFirst = true
+ }
+ }
+
+ private fun isRule(ruleStr: String): Boolean {
+ return ruleStr.startsWith('@') //js首个字符不可能是@,除非是装饰器,所以@开头规定为规则
+ || ruleStr.startsWith("$.")
+ || ruleStr.startsWith("$[")
+ || ruleStr.startsWith("//")
+ }
+ }
+
+ enum class Mode {
+ XPath, Json, Default, Js, Regex
+ }
+
+ fun put(key: String, value: String): String {
+ chapter?.putVariable(key, value)
+ ?: book?.putVariable(key, value)
+ ?: ruleData.putVariable(key, value)
+ return value
+ }
+
+ fun get(key: String): String {
+ when (key) {
+ "bookName" -> book?.let {
+ return it.name
+ }
+ "title" -> chapter?.let {
+ return it.title
+ }
+ }
+ return chapter?.variableMap?.get(key)
+ ?: book?.variableMap?.get(key)
+ ?: ruleData.variableMap[key]
+ ?: ""
+ }
+
+ /**
+ * 执行JS
+ */
+ fun evalJS(jsStr: String, result: Any?): Any? {
+ val bindings = SimpleBindings()
+ bindings["java"] = this
+ bindings["cookie"] = CookieStore
+ bindings["cache"] = CacheManager
+ bindings["source"] = source
+ bindings["book"] = book
+ bindings["result"] = result
+ bindings["baseUrl"] = baseUrl
+ bindings["chapter"] = chapter
+ bindings["title"] = chapter?.title
+ bindings["src"] = content
+ bindings["nextChapterUrl"] = nextChapterUrl
+ return SCRIPT_ENGINE.eval(jsStr, bindings)
+ }
+
+ override fun getSource(): BaseSource? {
+ return source
+ }
+
+ /**
+ * js实现跨域访问,不能删
+ */
+ override fun ajax(urlStr: String): String? {
+ return runBlocking {
+ kotlin.runCatching {
+ val analyzeUrl = AnalyzeUrl(urlStr, source = source, ruleData = book)
+ analyzeUrl.getStrResponseAwait().body
+ }.onFailure {
+ log("ajax(${urlStr}) error\n${it.stackTraceToString()}")
+ Log.e(TAG, it.toString())
+ }.getOrElse {
+ it.message
+ }
+ }
+ }
+
+ /**
+ * 章节数转数字
+ */
+ fun toNumChapter(s: String?): String? {
+ s ?: return null
+ val matcher = titleNumPattern.matcher(s)
+ if (matcher.find()) {
+ return "${matcher.group(1)}${StringUtils.stringToInt(matcher.group(2))}${matcher.group(3)}"
+ }
+ return s
+ }
+
+ companion object {
+ private val putPattern = Pattern.compile("@put:(\\{[^}]+?\\})", Pattern.CASE_INSENSITIVE)
+ private val evalPattern =
+ Pattern.compile("@get:\\{[^}]+?\\}|\\{\\{[\\w\\W]*?\\}\\}", Pattern.CASE_INSENSITIVE)
+ private val regexPattern = Pattern.compile("\\$\\d{1,2}")
+ private val titleNumPattern = Pattern.compile("(第)(.+?)(章)")
+ }
+
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeUrl.kt
new file mode 100644
index 0000000..b7d09cb
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeUrl.kt
@@ -0,0 +1,570 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+import android.annotation.SuppressLint
+import androidx.annotation.Keep
+import com.bumptech.glide.load.model.GlideUrl
+import com.bumptech.glide.load.model.LazyHeaders
+import kotlinx.coroutines.runBlocking
+import okhttp3.Response
+import xyz.fycz.myreader.common.APPCONST.*
+import xyz.fycz.myreader.greendao.entity.Book
+import xyz.fycz.myreader.greendao.entity.Chapter
+import xyz.fycz.myreader.greendao.service.CacheManager
+import xyz.fycz.myreader.greendao.service.CookieStore
+import xyz.fycz.myreader.model.third3.BaseSource
+import xyz.fycz.myreader.model.third3.ConcurrentException
+import xyz.fycz.myreader.model.third3.http.*
+import xyz.fycz.myreader.util.utils.*
+import xyz.fycz.myreader.util.utils.UrlEncoderUtils
+import java.net.URLEncoder
+import java.util.*
+import java.util.regex.Pattern
+import javax.script.SimpleBindings
+import kotlin.collections.HashMap
+
+/**
+ * Created by GKF on 2018/1/24.
+ * 搜索URL规则解析
+ */
+@Suppress("unused", "MemberVisibilityCanBePrivate")
+@Keep
+@SuppressLint("DefaultLocale")
+class AnalyzeUrl(
+ val mUrl: String,
+ val key: String? = null,
+ val page: Int? = null,
+ val speakText: String? = null,
+ val speakSpeed: Int? = null,
+ var baseUrl: String = "",
+ private val source: BaseSource? = null,
+ private val ruleData: RuleDataInterface? = null,
+ private val chapter: Chapter? = null,
+ headerMapF: Map? = null,
+) : JsExtensions {
+ companion object {
+ val paramPattern: Pattern = Pattern.compile("\\s*,\\s*(?=\\{)")
+ private val pagePattern = Pattern.compile("<(.*?)>")
+ private val concurrentRecordMap = hashMapOf()
+ }
+
+ var ruleUrl = ""
+ private set
+ var url: String = ""
+ private set
+ var body: String? = null
+ private set
+ var type: String? = null
+ private set
+ val headerMap = HashMap()
+ private var urlNoQuery: String = ""
+ private var queryStr: String? = null
+ private val fieldMap = LinkedHashMap()
+ private var charset: String? = null
+ private var method = RequestMethod.GET
+ private var proxy: String? = null
+ private var retry: Int = 0
+ private var useWebView: Boolean = false
+ private var webJs: String? = null
+
+ init {
+ val urlMatcher = paramPattern.matcher(baseUrl)
+ if (urlMatcher.find()) baseUrl = baseUrl.substring(0, urlMatcher.start())
+ headerMapF?.let {
+ headerMap.putAll(it)
+ if (it.containsKey("proxy")) {
+ proxy = it["proxy"]
+ headerMap.remove("proxy")
+ }
+ }
+ initUrl()
+ }
+
+ /**
+ * 处理url
+ */
+ fun initUrl() {
+ ruleUrl = mUrl
+ //执行@js,
+ analyzeJs()
+ //替换参数
+ replaceKeyPageJs()
+ //处理URL
+ analyzeUrl()
+ }
+
+ /**
+ * 执行@js,
+ */
+ private fun analyzeJs() {
+ var start = 0
+ var tmp: String
+ val jsMatcher = JS_PATTERN_3.matcher(ruleUrl)
+ while (jsMatcher.find()) {
+ if (jsMatcher.start() > start) {
+ tmp =
+ ruleUrl.substring(start, jsMatcher.start()).trim { it <= ' ' }
+ if (tmp.isNotEmpty()) {
+ ruleUrl = tmp.replace("@result", ruleUrl)
+ }
+ }
+ ruleUrl = evalJS(jsMatcher.group(2) ?: jsMatcher.group(1), ruleUrl) as String
+ start = jsMatcher.end()
+ }
+ if (ruleUrl.length > start) {
+ tmp = ruleUrl.substring(start).trim { it <= ' ' }
+ if (tmp.isNotEmpty()) {
+ ruleUrl = tmp.replace("@result", ruleUrl)
+ }
+ }
+ }
+
+ /**
+ * 替换关键字,页数,JS
+ */
+ private fun replaceKeyPageJs() { //先替换内嵌规则再替换页数规则,避免内嵌规则中存在大于小于号时,规则被切错
+ //js
+ if (ruleUrl.contains("{{") && ruleUrl.contains("}}")) {
+ val analyze = RuleAnalyzer(ruleUrl) //创建解析
+ //替换所有内嵌{{js}}
+ val url = analyze.innerRule("{{", "}}") {
+ val jsEval = evalJS(it) ?: ""
+ when {
+ jsEval is String -> jsEval
+ jsEval is Double && jsEval % 1.0 == 0.0 -> String.format("%.0f", jsEval)
+ else -> jsEval.toString()
+ }
+ }
+ if (url.isNotEmpty()) ruleUrl = url
+ }
+ //page
+ page?.let {
+ val matcher = pagePattern.matcher(ruleUrl)
+ while (matcher.find()) {
+ val pages = matcher.group(1)!!.split(",")
+ ruleUrl = if (page < pages.size) { //pages[pages.size - 1]等同于pages.last()
+ ruleUrl.replace(matcher.group(), pages[page - 1].trim { it <= ' ' })
+ } else {
+ ruleUrl.replace(matcher.group(), pages.last().trim { it <= ' ' })
+ }
+ }
+ }
+ }
+
+ /**
+ * 解析Url
+ */
+ private fun analyzeUrl() {
+ //replaceKeyPageJs已经替换掉额外内容,此处url是基础形式,可以直接切首个‘,’之前字符串。
+ val urlMatcher = paramPattern.matcher(ruleUrl)
+ val urlNoOption =
+ if (urlMatcher.find()) ruleUrl.substring(0, urlMatcher.start()) else ruleUrl
+ url = NetworkUtils.getAbsoluteURL(baseUrl, urlNoOption)
+ NetworkUtils.getBaseUrl(url)?.let {
+ baseUrl = it
+ }
+ if (urlNoOption.length != ruleUrl.length) {
+ GSON.fromJsonObject(ruleUrl.substring(urlMatcher.end()))?.let { option ->
+ option.method?.let {
+ if (it.equals("POST", true)) method = RequestMethod.POST
+ }
+ option.headers?.let { headers ->
+ if (headers is Map<*, *>) {
+ headers.forEach { entry ->
+ headerMap[entry.key.toString()] = entry.value.toString()
+ }
+ } else if (headers is String) {
+ GSON.fromJsonObject>(headers)
+ ?.let { headerMap.putAll(it) }
+ }
+ }
+ option.body?.let {
+ body = if (it is String) it else GSON.toJson(it)
+ }
+ type = option.type
+ charset = option.charset
+ retry = option.retry
+ useWebView = option.webView?.toString()?.isNotBlank() == true
+ webJs = option.webJs
+ option.js?.let { jsStr ->
+ evalJS(jsStr, url)?.toString()?.let {
+ url = it
+ }
+ }
+ }
+ }
+ headerMap[UA_NAME] ?: let {
+ headerMap[UA_NAME] = DEFAULT_USER_AGENT
+ }
+ urlNoQuery = url
+ when (method) {
+ RequestMethod.GET -> {
+ val pos = url.indexOf('?')
+ if (pos != -1) {
+ analyzeFields(url.substring(pos + 1))
+ urlNoQuery = url.substring(0, pos)
+ }
+ }
+ RequestMethod.POST -> body?.let {
+ if (!it.isJson()) {
+ analyzeFields(it)
+ }
+ }
+ }
+ }
+
+ /**
+ * 解析QueryMap
+ */
+ private fun analyzeFields(fieldsTxt: String) {
+ queryStr = fieldsTxt
+ val queryS = fieldsTxt.splitNotBlank("&")
+ for (query in queryS) {
+ val queryM = query.splitNotBlank("=")
+ val value = if (queryM.size > 1) queryM[1] else ""
+ if (charset.isNullOrEmpty()) {
+ if (UrlEncoderUtils.hasUrlEncoded(value)) {
+ fieldMap[queryM[0]] = value
+ } else {
+ fieldMap[queryM[0]] = URLEncoder.encode(value, "UTF-8")
+ }
+ } else if (charset == "escape") {
+ fieldMap[queryM[0]] = EncoderUtils.escape(value)
+ } else {
+ fieldMap[queryM[0]] = URLEncoder.encode(value, charset)
+ }
+ }
+ }
+
+ /**
+ * 执行JS
+ */
+ fun evalJS(jsStr: String, result: Any? = null): Any? {
+ val bindings = SimpleBindings()
+ bindings["java"] = this
+ bindings["baseUrl"] = baseUrl
+ bindings["cookie"] = CookieStore
+ bindings["cache"] = CacheManager
+ bindings["page"] = page
+ bindings["key"] = key
+ bindings["speakText"] = speakText
+ bindings["speakSpeed"] = speakSpeed
+ bindings["book"] = ruleData as? Book
+ bindings["source"] = source
+ bindings["result"] = result
+ return SCRIPT_ENGINE.eval(jsStr, bindings)
+ }
+
+ fun put(key: String, value: String): String {
+ chapter?.putVariable(key, value)
+ ?: ruleData?.putVariable(key, value)
+ return value
+ }
+
+ fun get(key: String): String {
+ when (key) {
+ "bookName" -> (ruleData as? Book)?.let {
+ return it.name
+ }
+ "title" -> chapter?.let {
+ return it.title
+ }
+ }
+ return chapter?.variableMap?.get(key)
+ ?: ruleData?.variableMap?.get(key)
+ ?: ""
+ }
+
+ /**
+ * 开始访问,并发判断
+ */
+ private fun fetchStart(): ConcurrentRecord? {
+ source ?: return null
+ val concurrentRate = source.getConcurrentRateKt()
+ if (concurrentRate.isNullOrEmpty()) {
+ return null
+ }
+ val rateIndex = concurrentRate.indexOf("/")
+ var fetchRecord = concurrentRecordMap[source.getKey()]
+ if (fetchRecord == null) {
+ fetchRecord = ConcurrentRecord(rateIndex > 0, System.currentTimeMillis(), 1)
+ concurrentRecordMap[source.getKey()] = fetchRecord
+ return fetchRecord
+ }
+ val waitTime: Int = synchronized(fetchRecord) {
+ try {
+ if (rateIndex == -1) {
+ if (fetchRecord.frequency > 0) {
+ return@synchronized concurrentRate.toInt()
+ }
+ val nextTime = fetchRecord.time + concurrentRate.toInt()
+ if (System.currentTimeMillis() >= nextTime) {
+ fetchRecord.time = System.currentTimeMillis()
+ fetchRecord.frequency = 1
+ return@synchronized 0
+ }
+ return@synchronized (nextTime - System.currentTimeMillis()).toInt()
+ } else {
+ val sj = concurrentRate.substring(rateIndex + 1)
+ val nextTime = fetchRecord.time + sj.toInt()
+ if (System.currentTimeMillis() >= nextTime) {
+ fetchRecord.time = System.currentTimeMillis()
+ fetchRecord.frequency = 1
+ return@synchronized 0
+ }
+ val cs = concurrentRate.substring(0, rateIndex)
+ if (fetchRecord.frequency > cs.toInt()) {
+ return@synchronized (nextTime - System.currentTimeMillis()).toInt()
+ } else {
+ fetchRecord.frequency = fetchRecord.frequency + 1
+ return@synchronized 0
+ }
+ }
+ } catch (e: Exception) {
+ return@synchronized 0
+ }
+ }
+ if (waitTime > 0) {
+ throw ConcurrentException("根据并发率还需等待${waitTime}毫秒才可以访问", waitTime = waitTime)
+ }
+ return fetchRecord
+ }
+
+ /**
+ * 访问结束
+ */
+ private fun fetchEnd(concurrentRecord: ConcurrentRecord?) {
+ if (concurrentRecord != null && !concurrentRecord.concurrent) {
+ synchronized(concurrentRecord) {
+ concurrentRecord.frequency = concurrentRecord.frequency - 1
+ }
+ }
+ }
+
+ /**
+ * 访问网站,返回StrResponse
+ */
+ suspend fun getStrResponseAwait(
+ jsStr: String? = null,
+ sourceRegex: String? = null,
+ useWebView: Boolean = true,
+ ): StrResponse {
+ if (type != null) {
+ return StrResponse(url, StringUtils.byteToHexString(getByteArrayAwait()))
+ }
+ val concurrentRecord = fetchStart()
+ setCookie(source?.getKey())
+ val strResponse: StrResponse
+ if (this.useWebView && useWebView) {
+ strResponse = when (method) {
+ RequestMethod.POST -> {
+ val body = getProxyClient(proxy, source?.getNoProxy() == true).newCallStrResponse(retry) {
+ addHeaders(headerMap)
+ url(urlNoQuery)
+ if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
+ postForm(fieldMap, true)
+ } else {
+ postJson(body)
+ }
+ }.body
+ BackstageWebView(
+ url = url,
+ html = body,
+ tag = source?.getKey(),
+ javaScript = webJs ?: jsStr,
+ sourceRegex = sourceRegex,
+ headerMap = headerMap
+ ).getStrResponse()
+ }
+ else -> BackstageWebView(
+ url = url,
+ tag = source?.getKey(),
+ javaScript = webJs ?: jsStr,
+ sourceRegex = sourceRegex,
+ headerMap = headerMap
+ ).getStrResponse()
+ }
+ } else {
+ strResponse = getProxyClient(proxy, source?.getNoProxy() == true).newCallStrResponse(retry) {
+ addHeaders(headerMap)
+ when (method) {
+ RequestMethod.POST -> {
+ url(urlNoQuery)
+ if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
+ postForm(fieldMap, true)
+ } else {
+ postJson(body)
+ }
+ }
+ else -> get(urlNoQuery, fieldMap, true)
+ }
+ }
+ }
+ fetchEnd(concurrentRecord)
+ return strResponse
+ }
+
+ @JvmOverloads
+ fun getStrResponse(
+ jsStr: String? = null,
+ sourceRegex: String? = null,
+ useWebView: Boolean = true,
+ ): StrResponse {
+ return runBlocking {
+ getStrResponseAwait(jsStr, sourceRegex, useWebView)
+ }
+ }
+
+ /**
+ * 访问网站,返回Response
+ */
+ suspend fun getResponseAwait(): Response {
+ val concurrentRecord = fetchStart()
+ setCookie(source?.getKey())
+ @Suppress("BlockingMethodInNonBlockingContext")
+ val response = getProxyClient(proxy, source?.getNoProxy() == true).newCallResponse(retry) {
+ addHeaders(headerMap)
+ when (method) {
+ RequestMethod.POST -> {
+ url(urlNoQuery)
+ if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
+ postForm(fieldMap, true)
+ } else {
+ postJson(body)
+ }
+ }
+ else -> get(urlNoQuery, fieldMap, true)
+ }
+ }
+ fetchEnd(concurrentRecord)
+ return response
+ }
+
+ fun getResponse(): Response {
+ return runBlocking {
+ getResponseAwait()
+ }
+ }
+
+ /**
+ * 访问网站,返回ByteArray
+ */
+ suspend fun getByteArrayAwait(): ByteArray {
+ val concurrentRecord = fetchStart()
+ setCookie(source?.getKey())
+ @Suppress("BlockingMethodInNonBlockingContext")
+ val byteArray = getProxyClient(proxy, source?.getNoProxy() == true).newCallResponseBody(retry) {
+ addHeaders(headerMap)
+ when (method) {
+ RequestMethod.POST -> {
+ url(urlNoQuery)
+ if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
+ postForm(fieldMap, true)
+ } else {
+ postJson(body)
+ }
+ }
+ else -> get(urlNoQuery, fieldMap, true)
+ }
+ }.bytes()
+ fetchEnd(concurrentRecord)
+ return byteArray
+ }
+
+ fun getByteArray(): ByteArray {
+ return runBlocking {
+ getByteArrayAwait()
+ }
+ }
+
+ /**
+ * 上传文件
+ */
+ suspend fun upload(fileName: String, file: Any, contentType: String): StrResponse {
+ return getProxyClient(proxy, source?.getNoProxy() == true).newCallStrResponse(retry) {
+ url(urlNoQuery)
+ val bodyMap = GSON.fromJsonObject>(body)!!
+ bodyMap.forEach { entry ->
+ if (entry.value.toString() == "fileRequest") {
+ bodyMap[entry.key] = mapOf(
+ Pair("fileName", fileName),
+ Pair("file", file),
+ Pair("contentType", contentType)
+ )
+ }
+ }
+ postMultipart(type, bodyMap)
+ }
+ }
+
+ private fun setCookie(tag: String?) {
+ if (tag != null) {
+ val cookie = CookieStore.getCookie(tag)
+ if (cookie.isNotEmpty()) {
+ val cookieMap = CookieStore.cookieToMap(cookie)
+ val customCookieMap = CookieStore.cookieToMap(headerMap["Cookie"] ?: "")
+ cookieMap.putAll(customCookieMap)
+ val newCookie = CookieStore.mapToCookie(cookieMap)
+ newCookie?.let {
+ headerMap.put("Cookie", it)
+ }
+ }
+ }
+ }
+
+ fun getGlideUrl(): GlideUrl {
+ val headers = LazyHeaders.Builder()
+ headerMap.forEach { (key, value) ->
+ headers.addHeader(key, value)
+ }
+ return GlideUrl(url, headers.build())
+ }
+
+ fun getUserAgent(): String {
+ return headerMap[UA_NAME] ?: DEFAULT_USER_AGENT
+ }
+
+ fun isPost(): Boolean {
+ return method == RequestMethod.POST
+ }
+
+ override fun getSource(): BaseSource? {
+ return source
+ }
+
+ data class UrlOption(
+ val method: String?,
+ val charset: String?,
+ val headers: Any?,
+ val body: Any?,
+ val type: String?,
+ val js: String?,
+ val retry: Int = 0,
+ val webView: Any?,
+ val webJs: String?,
+ )
+
+ data class ConcurrentRecord(
+ val concurrent: Boolean,
+ var time: Long,
+ var frequency: Int
+ )
+
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/JsExtensions.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/JsExtensions.kt
new file mode 100644
index 0000000..82cda80
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/JsExtensions.kt
@@ -0,0 +1,676 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+import android.net.Uri
+import android.util.Base64
+import android.util.Log
+import androidx.annotation.Keep
+import kotlinx.coroutines.Dispatchers.IO
+import kotlinx.coroutines.async
+import kotlinx.coroutines.runBlocking
+import nl.siegmann.epublib.epub.PackageDocumentBase.dateFormat
+import org.jsoup.Connection
+import org.jsoup.Jsoup
+import xyz.fycz.myreader.application.App
+import xyz.fycz.myreader.common.APPCONST
+import xyz.fycz.myreader.greendao.service.CacheManager
+import xyz.fycz.myreader.greendao.service.CookieStore
+import xyz.fycz.myreader.model.third3.BaseSource
+import xyz.fycz.myreader.model.third3.Debug
+import xyz.fycz.myreader.model.third3.http.*
+import xyz.fycz.myreader.util.ZipUtils
+import xyz.fycz.myreader.util.utils.*
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.net.URLEncoder
+import java.nio.charset.Charset
+import java.text.SimpleDateFormat
+import java.util.*
+import java.util.zip.ZipEntry
+import java.util.zip.ZipInputStream
+
+/**
+ * js扩展类, 在js中通过java变量调用
+ * 所有对于文件的读写删操作都是相对路径,只能操作阅读缓存内的文件
+ * /android/data/{package}/cache/...
+ */
+@Keep
+@Suppress("unused")
+interface JsExtensions {
+
+ val TAG: String?
+ get() = JsExtensions::class.simpleName
+
+ fun getSource(): BaseSource?
+
+ /**
+ * 访问网络,返回String
+ */
+ fun ajax(urlStr: String): String? {
+ return runBlocking {
+ kotlin.runCatching {
+ val analyzeUrl = AnalyzeUrl(urlStr, source = getSource())
+ analyzeUrl.getStrResponseAwait().body
+ }.onFailure {
+ log("ajax(${urlStr}) error\n${it.stackTraceToString()}")
+ Log.e(TAG, it.toString())
+ }.getOrElse {
+ it.message
+ }
+ }
+ }
+
+ /**
+ * 并发访问网络
+ */
+ fun ajaxAll(urlList: Array): Array {
+ return runBlocking {
+ val asyncArray = Array(urlList.size) {
+ async(IO) {
+ val url = urlList[it]
+ val analyzeUrl = AnalyzeUrl(url, source = getSource())
+ analyzeUrl.getStrResponseAwait()
+ }
+ }
+ val resArray = Array(urlList.size) {
+ asyncArray[it].await()
+ }
+ resArray
+ }
+ }
+
+ /**
+ * 访问网络,返回Response
+ */
+ fun connect(urlStr: String): StrResponse {
+ return runBlocking {
+ val analyzeUrl = AnalyzeUrl(urlStr, source = getSource())
+ kotlin.runCatching {
+ analyzeUrl.getStrResponseAwait()
+ }.onFailure {
+ log("connect(${urlStr}) error\n${it.stackTraceToString()}")
+ Log.e(TAG, it.toString())
+ }.getOrElse {
+ StrResponse(analyzeUrl.url, it.localizedMessage)
+ }
+ }
+ }
+
+ fun connect(urlStr: String, header: String?): StrResponse {
+ return runBlocking {
+ val headerMap = GSON.fromJsonObject>(header)
+ val analyzeUrl = AnalyzeUrl(urlStr, headerMapF = headerMap, source = getSource())
+ kotlin.runCatching {
+ analyzeUrl.getStrResponseAwait()
+ }.onFailure {
+ log("ajax($urlStr,$header) error\n${it.stackTraceToString()}")
+ Log.e(TAG, it.toString())
+ }.getOrElse {
+ StrResponse(analyzeUrl.url, it.localizedMessage)
+ }
+ }
+ }
+
+ /**
+ * 使用webView访问网络
+ * @param html 直接用webView载入的html, 如果html为空直接访问url
+ * @param url html内如果有相对路径的资源不传入url访问不了
+ * @param js 用来取返回值的js语句, 没有就返回整个源代码
+ * @return 返回js获取的内容
+ */
+ fun webView(html: String?, url: String?, js: String?): String? {
+ return runBlocking {
+ BackstageWebView(
+ url = url,
+ html = html,
+ javaScript = js
+ ).getStrResponse().body
+ }
+ }
+
+ /**
+ * 实现16进制字符串转文件
+ * @param content 需要转成文件的16进制字符串
+ * @param url 通过url里的参数来判断文件类型
+ * @return 相对路径
+ */
+ fun downloadFile(content: String, url: String): String {
+ val type = AnalyzeUrl(url, source = getSource()).type ?: return ""
+ val zipPath = FileUtils.getPath(
+ FileUtils.getFile(FileUtils.getCachePath()),
+ "${MD5Utils.md5Encode16(url)}.${type}"
+ )
+ FileUtils.deleteFile(zipPath)
+ val zipFile = FileUtils.getFile(zipPath)
+ StringUtils.hexStringToByte(content).let {
+ if (it.isNotEmpty()) {
+ zipFile.writeBytes(it)
+ }
+ }
+ return zipPath.substring(FileUtils.getCachePath().length)
+ }
+
+ /**
+ * js实现重定向拦截,网络访问get
+ */
+ fun get(urlStr: String, headers: Map): Connection.Response {
+ return Jsoup.connect(urlStr)
+ .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory)
+ .ignoreContentType(true)
+ .followRedirects(false)
+ .headers(headers)
+ .method(Connection.Method.GET)
+ .execute()
+ }
+
+ /**
+ * 网络访问post
+ */
+ fun post(urlStr: String, body: String, headers: Map): Connection.Response {
+ return Jsoup.connect(urlStr)
+ .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory)
+ .ignoreContentType(true)
+ .followRedirects(false)
+ .requestBody(body)
+ .headers(headers)
+ .method(Connection.Method.POST)
+ .execute()
+ }
+
+ /**
+ *js实现读取cookie
+ */
+ fun getCookie(tag: String, key: String? = null): String {
+ val cookie = CookieStore.getCookie(tag)
+ val cookieMap = CookieStore.cookieToMap(cookie)
+ return if (key != null) {
+ cookieMap[key] ?: ""
+ } else {
+ cookie
+ }
+ }
+
+ /**
+ * js实现解码,不能删
+ */
+ fun base64Decode(str: String): String {
+ return EncoderUtils.base64Decode(str, Base64.NO_WRAP)
+ }
+
+ fun base64Decode(str: String, flags: Int): String {
+ return EncoderUtils.base64Decode(str, flags)
+ }
+
+ fun base64DecodeToByteArray(str: String?): ByteArray? {
+ if (str.isNullOrBlank()) {
+ return null
+ }
+ return Base64.decode(str, Base64.DEFAULT)
+ }
+
+ fun base64DecodeToByteArray(str: String?, flags: Int): ByteArray? {
+ if (str.isNullOrBlank()) {
+ return null
+ }
+ return Base64.decode(str, flags)
+ }
+
+ fun base64Encode(str: String): String? {
+ return EncoderUtils.base64Encode(str, Base64.NO_WRAP)
+ }
+
+ fun base64Encode(str: String, flags: Int): String? {
+ return EncoderUtils.base64Encode(str, flags)
+ }
+
+ fun md5Encode(str: String): String {
+ return MD5Utils.md5Encode(str)
+ }
+
+ fun md5Encode16(str: String): String {
+ return MD5Utils.md5Encode16(str)
+ }
+
+ /**
+ * 格式化时间
+ */
+ fun timeFormatUTC(time: Long, format: String, sh: Int): String? {
+ val utc = SimpleTimeZone(sh, "UTC")
+ return SimpleDateFormat(format, Locale.getDefault()).run {
+ timeZone = utc
+ format(Date(time))
+ }
+ }
+
+ /**
+ * 时间格式化
+ */
+ fun timeFormat(time: Long): String {
+ return dateFormat.format(Date(time))
+ }
+
+ /**
+ * utf8编码转gbk编码
+ */
+ fun utf8ToGbk(str: String): String {
+ val utf8 = String(str.toByteArray(charset("UTF-8")))
+ val unicode = String(utf8.toByteArray(), charset("UTF-8"))
+ return String(unicode.toByteArray(charset("GBK")))
+ }
+
+ fun encodeURI(str: String): String {
+ return try {
+ URLEncoder.encode(str, "UTF-8")
+ } catch (e: Exception) {
+ ""
+ }
+ }
+
+ fun encodeURI(str: String, enc: String): String {
+ return try {
+ URLEncoder.encode(str, enc)
+ } catch (e: Exception) {
+ ""
+ }
+ }
+
+ fun htmlFormat(str: String): String {
+ return HtmlFormatter.format(str)
+// return HtmlFormatter.formatKeepImg(str)
+ }
+
+ //****************文件操作******************//
+
+ /**
+ * 获取本地文件
+ * @param path 相对路径
+ * @return File
+ */
+ fun getFile(path: String): File {
+ val cachePath = FileUtils.getCachePath()
+ val aPath = if (path.startsWith(File.separator)) {
+ cachePath + path
+ } else {
+ cachePath + File.separator + path
+ }
+ return File(aPath)
+ }
+
+ fun readFile(path: String): ByteArray? {
+ val file = getFile(path)
+ if (file.exists()) {
+ return file.readBytes()
+ }
+ return null
+ }
+
+ fun readTxtFile(path: String): String {
+ val file = getFile(path)
+ if (file.exists()) {
+ val charsetName = EncodingDetect.getJavaEncode(file)
+ return String(file.readBytes(), charset(charsetName))
+ }
+ return ""
+ }
+
+ fun readTxtFile(path: String, charsetName: String): String {
+ val file = getFile(path)
+ if (file.exists()) {
+ return String(file.readBytes(), charset(charsetName))
+ }
+ return ""
+ }
+
+ /**
+ * 删除本地文件
+ */
+ fun deleteFile(path: String) {
+ FileUtils.deleteFile(path)
+ }
+
+ /**
+ * js实现压缩文件解压
+ * @param zipPath 相对路径
+ * @return 相对路径
+ */
+ fun unzipFile(zipPath: String): String {
+ if (zipPath.isEmpty()) return ""
+ val unzipPath = FileUtils.getPath(
+ FileUtils.getFile(FileUtils.getCachePath()),
+ FileUtils.getNameExcludeExtension(zipPath)
+ )
+ FileUtils.deleteFile(unzipPath)
+ val zipFile = getFile(zipPath)
+ val unzipFolder = FileUtils.getFile(unzipPath)
+ ZipUtils.unzipFile(zipFile, unzipFolder)
+ FileUtils.deleteFile(zipFile.absolutePath)
+ return unzipPath.substring(FileUtils.getCachePath().length)
+ }
+
+ /**
+ * js实现文件夹内所有文件读取
+ */
+ fun getTxtInFolder(unzipPath: String): String {
+ if (unzipPath.isEmpty()) return ""
+ val unzipFolder = getFile(unzipPath)
+ val contents = StringBuilder()
+ unzipFolder.listFiles().let {
+ if (it != null) {
+ for (f in it) {
+ val charsetName = EncodingDetect.getJavaEncode(f)
+ contents.append(String(f.readBytes(), charset(charsetName)))
+ .append("\n")
+ }
+ contents.deleteCharAt(contents.length - 1)
+ }
+ }
+ FileUtils.deleteFile(unzipFolder.absolutePath)
+ return contents.toString()
+ }
+
+ /**
+ * 获取网络zip文件里面的数据
+ * @param url zip文件的链接或十六进制字符串
+ * @param path 所需获取文件在zip内的路径
+ * @return zip指定文件的数据
+ */
+ fun getZipStringContent(url: String, path: String): String {
+ val byteArray = getZipByteArrayContent(url, path) ?: return ""
+ val charsetName = EncodingDetect.getJavaEncode(byteArray)
+ return String(byteArray, Charset.forName(charsetName))
+ }
+
+ fun getZipStringContent(url: String, path: String, charsetName: String): String {
+ val byteArray = getZipByteArrayContent(url, path) ?: return ""
+ return String(byteArray, Charset.forName(charsetName))
+ }
+
+ /**
+ * 获取网络zip文件里面的数据
+ * @param url zip文件的链接或十六进制字符串
+ * @param path 所需获取文件在zip内的路径
+ * @return zip指定文件的数据
+ */
+ fun getZipByteArrayContent(url: String, path: String): ByteArray? {
+ val bytes = if (url.startsWith("http://") || url.startsWith("https://")) {
+ runBlocking {
+ return@runBlocking okHttpClient.newCallResponseBody { url(url) }.bytes()
+ }
+ } else {
+ StringUtils.hexStringToByte(url)
+ }
+ val bos = ByteArrayOutputStream()
+ val zis = ZipInputStream(ByteArrayInputStream(bytes))
+ var entry: ZipEntry? = zis.nextEntry
+ while (entry != null) {
+ if (entry.name.equals(path)) {
+ zis.use { it.copyTo(bos) }
+ return bos.toByteArray()
+ }
+ entry = zis.nextEntry
+ }
+ log("getZipContent 未发现内容")
+ return null
+ }
+
+ //******************文件操作************************//
+
+ /**
+ * 解析字体,返回字体解析类
+ */
+ fun queryBase64TTF(base64: String?): QueryTTF? {
+ base64DecodeToByteArray(base64)?.let {
+ return QueryTTF(it)
+ }
+ return null
+ }
+
+ /**
+ * 返回字体解析类
+ * @param str 支持url,本地文件,base64,自动判断,自动缓存
+ */
+ fun queryTTF(str: String?): QueryTTF? {
+ str ?: return null
+ val key = md5Encode16(str)
+ var qTTF = CacheManager.getQueryTTF(key)
+ if (qTTF != null) return qTTF
+ val font: ByteArray? = when {
+ str.isAbsUrl() -> runBlocking {
+ var x = CacheManager.getByteArray(key)
+ if (x == null) {
+ x = okHttpClient.newCallResponseBody { url(str) }.bytes()
+ x.let {
+ CacheManager.put(key, it)
+ }
+ }
+ return@runBlocking x
+ }
+ str.isContentScheme() -> DocumentUtil.readBytes(App.getmContext(), Uri.parse(str))
+ str.startsWith("/storage") -> File(str).readBytes()
+ else -> base64DecodeToByteArray(str)
+ }
+ font ?: return null
+ qTTF = QueryTTF(font)
+ CacheManager.put(key, qTTF)
+ return qTTF
+ }
+
+ /**
+ * @param text 包含错误字体的内容
+ * @param font1 错误的字体
+ * @param font2 正确的字体
+ */
+ fun replaceFont(
+ text: String,
+ font1: QueryTTF?,
+ font2: QueryTTF?
+ ): String {
+ if (font1 == null || font2 == null) return text
+ val contentArray = text.toCharArray()
+ contentArray.forEachIndexed { index, s ->
+ val oldCode = s.code
+ if (font1.inLimit(s)) {
+ val glyf = font1.getGlyfByCode(oldCode)
+ val code = font2.getCodeByGlyf(glyf)
+ if (code != 0) {
+ contentArray[index] = code.toChar()
+ }
+ }
+ }
+ return contentArray.joinToString("")
+ }
+
+ /**
+ * 输出调试日志
+ */
+ fun log(msg: String): String {
+ getSource()?.let {
+ Debug.log(it.getKey(), msg)
+ } ?: Debug.log(msg)
+ if (App.isDebug()) {
+ Log.d(TAG + "-" + getSource()?.getKey(), msg)
+ }
+ return msg
+ }
+
+ /**
+ * 生成UUID
+ */
+ fun randomUUID(): String {
+ return UUID.randomUUID().toString()
+ }
+
+ /**
+ * AES 解码为 ByteArray
+ * @param str 传入的AES加密的数据
+ * @param key AES 解密的key
+ * @param transformation AES加密的方式
+ * @param iv ECB模式的偏移向量
+ */
+ fun aesDecodeToByteArray(
+ str: String, key: String, transformation: String, iv: String
+ ): ByteArray? {
+ return try {
+ EncoderUtils.decryptAES(
+ data = str.encodeToByteArray(),
+ key = key.encodeToByteArray(),
+ transformation,
+ iv.encodeToByteArray()
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, e.toString())
+ log(e.localizedMessage ?: "aesDecodeToByteArrayERROR")
+ null
+ }
+ }
+
+ /**
+ * AES 解码为 String
+ * @param str 传入的AES加密的数据
+ * @param key AES 解密的key
+ * @param transformation AES加密的方式
+ * @param iv ECB模式的偏移向量
+ */
+
+ fun aesDecodeToString(
+ str: String, key: String, transformation: String, iv: String
+ ): String? {
+ return aesDecodeToByteArray(str, key, transformation, iv)?.let { String(it) }
+ }
+
+ /**
+ * 已经base64的AES 解码为 ByteArray
+ * @param str 传入的AES Base64加密的数据
+ * @param key AES 解密的key
+ * @param transformation AES加密的方式
+ * @param iv ECB模式的偏移向量
+ */
+
+ fun aesBase64DecodeToByteArray(
+ str: String, key: String, transformation: String, iv: String
+ ): ByteArray? {
+ return try {
+ EncoderUtils.decryptBase64AES(
+ str.encodeToByteArray(),
+ key.encodeToByteArray(),
+ transformation,
+ iv.encodeToByteArray()
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, e.toString())
+ log(e.localizedMessage ?: "aesDecodeToByteArrayERROR")
+ null
+ }
+ }
+
+ /**
+ * 已经base64的AES 解码为 String
+ * @param str 传入的AES Base64加密的数据
+ * @param key AES 解密的key
+ * @param transformation AES加密的方式
+ * @param iv ECB模式的偏移向量
+ */
+
+ fun aesBase64DecodeToString(
+ str: String, key: String, transformation: String, iv: String
+ ): String? {
+ return aesBase64DecodeToByteArray(str, key, transformation, iv)?.let { String(it) }
+ }
+
+ /**
+ * 加密aes为ByteArray
+ * @param data 传入的原始数据
+ * @param key AES加密的key
+ * @param transformation AES加密的方式
+ * @param iv ECB模式的偏移向量
+ */
+ fun aesEncodeToByteArray(
+ data: String, key: String, transformation: String, iv: String
+ ): ByteArray? {
+ return try {
+ EncoderUtils.encryptAES(
+ data.encodeToByteArray(),
+ key = key.encodeToByteArray(),
+ transformation,
+ iv.encodeToByteArray()
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, e.toString())
+ log(e.localizedMessage ?: "aesEncodeToByteArrayERROR")
+ null
+ }
+ }
+
+ /**
+ * 加密aes为String
+ * @param data 传入的原始数据
+ * @param key AES加密的key
+ * @param transformation AES加密的方式
+ * @param iv ECB模式的偏移向量
+ */
+ fun aesEncodeToString(
+ data: String, key: String, transformation: String, iv: String
+ ): String? {
+ return aesEncodeToByteArray(data, key, transformation, iv)?.let { String(it) }
+ }
+
+ /**
+ * 加密aes后Base64化的ByteArray
+ * @param data 传入的原始数据
+ * @param key AES加密的key
+ * @param transformation AES加密的方式
+ * @param iv ECB模式的偏移向量
+ */
+ fun aesEncodeToBase64ByteArray(
+ data: String, key: String, transformation: String, iv: String
+ ): ByteArray? {
+ return try {
+ EncoderUtils.encryptAES2Base64(
+ data.encodeToByteArray(),
+ key.encodeToByteArray(),
+ transformation,
+ iv.encodeToByteArray()
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, e.toString())
+ log(e.localizedMessage ?: "aesEncodeToBase64ByteArrayERROR")
+ null
+ }
+ }
+
+ /**
+ * 加密aes后Base64化的String
+ * @param data 传入的原始数据
+ * @param key AES加密的key
+ * @param transformation AES加密的方式
+ * @param iv ECB模式的偏移向量
+ */
+ fun aesEncodeToBase64String(
+ data: String, key: String, transformation: String, iv: String
+ ): String? {
+ return aesEncodeToBase64ByteArray(data, key, transformation, iv)?.let { String(it) }
+ }
+
+ fun android(): String {
+ return APPCONST.androidId
+ }
+
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/QueryTTF.java b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/QueryTTF.java
new file mode 100644
index 0000000..4a777d6
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/QueryTTF.java
@@ -0,0 +1,621 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.lang3.tuple.Triple;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings({"FieldCanBeLocal", "StatementWithEmptyBody", "unused"})
+public class QueryTTF {
+ private static class Header {
+ public int majorVersion;
+ public int minorVersion;
+ public int numOfTables;
+ public int searchRange;
+ public int entrySelector;
+ public int rangeShift;
+ }
+
+ private static class Directory {
+ public String tag; // table name
+ public int checkSum; // Check sum
+ public int offset; // Offset from beginning of file
+ public int length; // length of the table in bytes
+ }
+
+ private static class NameLayout {
+ public int format;
+ public int count;
+ public int stringOffset;
+ public List records = new LinkedList<>();
+ }
+
+ private static class NameRecord {
+ public int platformID; // 平台标识符<0:Unicode, 1:Mac, 2:ISO, 3:Windows, 4:Custom>
+ public int encodingID; // 编码标识符
+ public int languageID; // 语言标识符
+ public int nameID; // 名称标识符
+ public int length; // 名称字符串的长度
+ public int offset; // 名称字符串相对于stringOffset的字节偏移量
+ }
+
+ private static class HeadLayout {
+ public int majorVersion;
+ public int minorVersion;
+ public int fontRevision;
+ public int checkSumAdjustment;
+ public int magicNumber;
+ public int flags;
+ public int unitsPerEm;
+ public long created;
+ public long modified;
+ public short xMin;
+ public short yMin;
+ public short xMax;
+ public short yMax;
+ public int macStyle;
+ public int lowestRecPPEM;
+ public short fontDirectionHint;
+ public short indexToLocFormat; // <0:loca是2字节数组, 1:loca是4字节数组>
+ public short glyphDataFormat;
+ }
+
+ private static class MaxpLayout {
+ public int majorVersion;
+ public int minorVersion;
+ public int numGlyphs; // 字体中的字形数量
+ public int maxPoints;
+ public int maxContours;
+ public int maxCompositePoints;
+ public int maxCompositeContours;
+ public int maxZones;
+ public int maxTwilightPoints;
+ public int maxStorage;
+ public int maxFunctionDefs;
+ public int maxInstructionDefs;
+ public int maxStackElements;
+ public int maxSizeOfInstructions;
+ public int maxComponentElements;
+ public int maxComponentDepth;
+ }
+
+ private static class CmapLayout {
+ public int version;
+ public int numTables;
+ public List records = new LinkedList<>();
+ public Map tables = new HashMap<>();
+ }
+
+ private static class CmapRecord {
+ public int platformID;
+ public int encodingID;
+ public int offset;
+ }
+
+ private static class CmapFormat {
+ public int format;
+ public int length;
+ public int language;
+ public byte[] glyphIdArray;
+ }
+
+ private static class CmapFormat4 extends CmapFormat {
+ public int segCountX2;
+ public int searchRange;
+ public int entrySelector;
+ public int rangeShift;
+ public int[] endCode;
+ public int reservedPad;
+ public int[] startCode;
+ public short[] idDelta;
+ public int[] idRangeOffset;
+ public int[] glyphIdArray;
+ }
+
+ private static class CmapFormat6 extends CmapFormat {
+ public int firstCode;
+ public int entryCount;
+ public int[] glyphIdArray;
+ }
+
+ private static class CmapFormat12 extends CmapFormat {
+ public int reserved;
+ public int length;
+ public int language;
+ public int numGroups;
+ public List> groups;
+ }
+
+ private static class GlyfLayout {
+ public short numberOfContours; // 非负值为简单字型,负值为符合字型
+ public short xMin;
+ public short yMin;
+ public short xMax;
+ public short yMax;
+ public int[] endPtsOfContours; // length=numberOfContours
+ public int instructionLength;
+ public byte[] instructions; // length=instructionLength
+ public byte[] flags;
+ public short[] xCoordinates; // length = flags.length
+ public short[] yCoordinates; // length = flags.length
+ }
+
+ private static class ByteArrayReader {
+ public int index;
+ public byte[] buffer;
+
+ public ByteArrayReader(byte[] buffer, int index) {
+ this.buffer = buffer;
+ this.index = index;
+ }
+
+ public long ReadUIntX(long len) {
+ long result = 0;
+ for (long i = 0; i < len; ++i) {
+ result <<= 8;
+ result |= buffer[index++] & 0xFF;
+ }
+ return result;
+ }
+
+ public long ReadUInt64() {
+ return ReadUIntX(8);
+ }
+
+ public int ReadUInt32() {
+ return (int) ReadUIntX(4);
+ }
+
+ public int ReadUInt16() {
+ return (int) ReadUIntX(2);
+ }
+
+ public short ReadInt16() {
+ return (short) ReadUIntX(2);
+ }
+
+ public short ReadUInt8() {
+ return (short) ReadUIntX(1);
+ }
+
+
+ public String ReadStrings(int len, Charset charset) {
+ byte[] result = len > 0 ? new byte[len] : null;
+ for (int i = 0; i < len; ++i) result[i] = buffer[index++];
+ return new String(result, charset);
+ }
+
+ public byte GetByte() {
+ return buffer[index++];
+ }
+
+ public byte[] GetBytes(int len) {
+ byte[] result = len > 0 ? new byte[len] : null;
+ for (int i = 0; i < len; ++i) result[i] = buffer[index++];
+ return result;
+ }
+
+ public int[] GetUInt16Array(int len) {
+ int[] result = len > 0 ? new int[len] : null;
+ for (int i = 0; i < len; ++i) result[i] = ReadUInt16();
+ return result;
+ }
+
+ public short[] GetInt16Array(int len) {
+ short[] result = len > 0 ? new short[len] : null;
+ for (int i = 0; i < len; ++i) result[i] = ReadInt16();
+ return result;
+ }
+ }
+
+ private final ByteArrayReader fontReader;
+ private final Header fileHeader = new Header();
+ private final List directorys = new LinkedList<>();
+ private final NameLayout name = new NameLayout();
+ private final HeadLayout head = new HeadLayout();
+ private final MaxpLayout maxp = new MaxpLayout();
+ private final List loca = new LinkedList<>();
+ private final CmapLayout Cmap = new CmapLayout();
+ private final List glyf = new LinkedList<>();
+ @SuppressWarnings("unchecked")
+ private final Pair[] pps = new Pair[]{
+ Pair.of(3, 10),
+ Pair.of(0, 4),
+ Pair.of(3, 1),
+ Pair.of(1, 0),
+ Pair.of(0, 3),
+ Pair.of(0, 1)
+ };
+
+ public final Map codeToGlyph = new HashMap<>();
+ public final Map glyphToCode = new HashMap<>();
+ private int limitMix = 0;
+ private int limitMax = 0;
+
+ /**
+ * 构造函数
+ *
+ * @param buffer 传入TTF字体二进制数组
+ */
+ public QueryTTF(byte[] buffer) {
+ fontReader = new ByteArrayReader(buffer, 0);
+ // 获取文件头
+ fileHeader.majorVersion = fontReader.ReadUInt16();
+ fileHeader.minorVersion = fontReader.ReadUInt16();
+ fileHeader.numOfTables = fontReader.ReadUInt16();
+ fileHeader.searchRange = fontReader.ReadUInt16();
+ fileHeader.entrySelector = fontReader.ReadUInt16();
+ fileHeader.rangeShift = fontReader.ReadUInt16();
+ // 获取目录
+ for (int i = 0; i < fileHeader.numOfTables; ++i) {
+ Directory d = new Directory();
+ d.tag = fontReader.ReadStrings(4, StandardCharsets.US_ASCII);
+ d.checkSum = fontReader.ReadUInt32();
+ d.offset = fontReader.ReadUInt32();
+ d.length = fontReader.ReadUInt32();
+ directorys.add(d);
+ }
+ // 解析表 name (字体信息,包含版权、名称、作者等...)
+ for (Directory Temp : directorys) {
+ if (Temp.tag.equals("name")) {
+ fontReader.index = Temp.offset;
+ name.format = fontReader.ReadUInt16();
+ name.count = fontReader.ReadUInt16();
+ name.stringOffset = fontReader.ReadUInt16();
+ for (int i = 0; i < name.count; ++i) {
+ NameRecord record = new NameRecord();
+ record.platformID = fontReader.ReadUInt16();
+ record.encodingID = fontReader.ReadUInt16();
+ record.languageID = fontReader.ReadUInt16();
+ record.nameID = fontReader.ReadUInt16();
+ record.length = fontReader.ReadUInt16();
+ record.offset = fontReader.ReadUInt16();
+ name.records.add(record);
+ }
+ }
+ }
+ // 解析表 head (获取 head.indexToLocFormat)
+ for (Directory Temp : directorys) {
+ if (Temp.tag.equals("head")) {
+ fontReader.index = Temp.offset;
+ head.majorVersion = fontReader.ReadUInt16();
+ head.minorVersion = fontReader.ReadUInt16();
+ head.fontRevision = fontReader.ReadUInt32();
+ head.checkSumAdjustment = fontReader.ReadUInt32();
+ head.magicNumber = fontReader.ReadUInt32();
+ head.flags = fontReader.ReadUInt16();
+ head.unitsPerEm = fontReader.ReadUInt16();
+ head.created = fontReader.ReadUInt64();
+ head.modified = fontReader.ReadUInt64();
+ head.xMin = fontReader.ReadInt16();
+ head.yMin = fontReader.ReadInt16();
+ head.xMax = fontReader.ReadInt16();
+ head.yMax = fontReader.ReadInt16();
+ head.macStyle = fontReader.ReadUInt16();
+ head.lowestRecPPEM = fontReader.ReadUInt16();
+ head.fontDirectionHint = fontReader.ReadInt16();
+ head.indexToLocFormat = fontReader.ReadInt16();
+ head.glyphDataFormat = fontReader.ReadInt16();
+ }
+ }
+ // 解析表 maxp (获取 maxp.numGlyphs)
+ for (Directory Temp : directorys) {
+ if (Temp.tag.equals("maxp")) {
+ fontReader.index = Temp.offset;
+ maxp.majorVersion = fontReader.ReadUInt16();
+ maxp.minorVersion = fontReader.ReadUInt16();
+ maxp.numGlyphs = fontReader.ReadUInt16();
+ maxp.maxPoints = fontReader.ReadUInt16();
+ maxp.maxContours = fontReader.ReadUInt16();
+ maxp.maxCompositePoints = fontReader.ReadUInt16();
+ maxp.maxCompositeContours = fontReader.ReadUInt16();
+ maxp.maxZones = fontReader.ReadUInt16();
+ maxp.maxTwilightPoints = fontReader.ReadUInt16();
+ maxp.maxStorage = fontReader.ReadUInt16();
+ maxp.maxFunctionDefs = fontReader.ReadUInt16();
+ maxp.maxInstructionDefs = fontReader.ReadUInt16();
+ maxp.maxStackElements = fontReader.ReadUInt16();
+ maxp.maxSizeOfInstructions = fontReader.ReadUInt16();
+ maxp.maxComponentElements = fontReader.ReadUInt16();
+ maxp.maxComponentDepth = fontReader.ReadUInt16();
+ }
+ }
+ // 解析表 loca (轮廓数据偏移地址表)
+ for (Directory Temp : directorys) {
+ if (Temp.tag.equals("loca")) {
+ fontReader.index = Temp.offset;
+ int offset = head.indexToLocFormat == 0 ? 2 : 4;
+ for (long i = 0; i < Temp.length; i += offset) {
+ loca.add(offset == 2 ? fontReader.ReadUInt16() << 1 : fontReader.ReadUInt32());
+ }
+ }
+ }
+ // 解析表 cmap (Unicode编码轮廓索引对照表)
+ for (Directory Temp : directorys) {
+ if (Temp.tag.equals("cmap")) {
+ fontReader.index = Temp.offset;
+ Cmap.version = fontReader.ReadUInt16();
+ Cmap.numTables = fontReader.ReadUInt16();
+
+ for (int i = 0; i < Cmap.numTables; ++i) {
+ CmapRecord record = new CmapRecord();
+ record.platformID = fontReader.ReadUInt16();
+ record.encodingID = fontReader.ReadUInt16();
+ record.offset = fontReader.ReadUInt32();
+ Cmap.records.add(record);
+ }
+ for (int i = 0; i < Cmap.numTables; ++i) {
+ int fmtOffset = Cmap.records.get(i).offset;
+ fontReader.index = Temp.offset + fmtOffset;
+ int EndIndex = fontReader.index;
+
+ int format = fontReader.ReadUInt16();
+ if (Cmap.tables.containsKey(fmtOffset)) continue;
+ if (format == 0) {
+ CmapFormat f = new CmapFormat();
+ f.format = format;
+ f.length = fontReader.ReadUInt16();
+ f.language = fontReader.ReadUInt16();
+ f.glyphIdArray = fontReader.GetBytes(f.length - 6);
+ Cmap.tables.put(fmtOffset, f);
+ } else if (format == 4) {
+ CmapFormat4 f = new CmapFormat4();
+ f.format = format;
+ f.length = fontReader.ReadUInt16();
+ f.language = fontReader.ReadUInt16();
+ f.segCountX2 = fontReader.ReadUInt16();
+ int segCount = f.segCountX2 >> 1;
+ f.searchRange = fontReader.ReadUInt16();
+ f.entrySelector = fontReader.ReadUInt16();
+ f.rangeShift = fontReader.ReadUInt16();
+ f.endCode = fontReader.GetUInt16Array(segCount);
+ f.reservedPad = fontReader.ReadUInt16();
+ f.startCode = fontReader.GetUInt16Array(segCount);
+ f.idDelta = fontReader.GetInt16Array(segCount);
+ f.idRangeOffset = fontReader.GetUInt16Array(segCount);
+ f.glyphIdArray = fontReader.GetUInt16Array((EndIndex + f.length - fontReader.index) >> 1);
+ Cmap.tables.put(fmtOffset, f);
+ } else if (format == 6) {
+ CmapFormat6 f = new CmapFormat6();
+ f.format = format;
+ f.length = fontReader.ReadUInt16();
+ f.language = fontReader.ReadUInt16();
+ f.firstCode = fontReader.ReadUInt16();
+ f.entryCount = fontReader.ReadUInt16();
+ f.glyphIdArray = fontReader.GetUInt16Array(f.entryCount);
+ Cmap.tables.put(fmtOffset, f);
+ } else if (format == 12) {
+ CmapFormat12 f = new CmapFormat12();
+ f.format = format;
+ f.reserved = fontReader.ReadUInt16();
+ f.length = fontReader.ReadUInt32();
+ f.language = fontReader.ReadUInt32();
+ f.numGroups = fontReader.ReadUInt32();
+ f.groups = new ArrayList<>(f.numGroups);
+ for (int n = 0; n < f.numGroups; ++n) {
+ f.groups.add(Triple.of(fontReader.ReadUInt32(), fontReader.ReadUInt32(), fontReader.ReadUInt32()));
+ }
+ Cmap.tables.put(fmtOffset, f);
+ }
+ }
+ }
+ }
+ // 解析表 glyf (字体轮廓数据表)
+ for (Directory Temp : directorys) {
+ if (Temp.tag.equals("glyf")) {
+ fontReader.index = Temp.offset;
+ for (int i = 0; i < maxp.numGlyphs; ++i) {
+ fontReader.index = Temp.offset + loca.get(i);
+
+ short numberOfContours = fontReader.ReadInt16();
+ if (numberOfContours > 0) {
+ GlyfLayout g = new GlyfLayout();
+ g.numberOfContours = numberOfContours;
+ g.xMin = fontReader.ReadInt16();
+ g.yMin = fontReader.ReadInt16();
+ g.xMax = fontReader.ReadInt16();
+ g.yMax = fontReader.ReadInt16();
+ g.endPtsOfContours = fontReader.GetUInt16Array(numberOfContours);
+ g.instructionLength = fontReader.ReadUInt16();
+ g.instructions = fontReader.GetBytes(g.instructionLength);
+ int flagLength = g.endPtsOfContours[g.endPtsOfContours.length - 1] + 1;
+ // 获取轮廓点描述标志
+ g.flags = new byte[flagLength];
+ for (int n = 0; n < flagLength; ++n) {
+ g.flags[n] = fontReader.GetByte();
+ if ((g.flags[n] & 0x08) != 0x00) {
+ for (int m = fontReader.ReadUInt8(); m > 0; --m) {
+ g.flags[++n] = g.flags[n - 1];
+ }
+ }
+ }
+ // 获取轮廓点描述x轴相对值
+ g.xCoordinates = new short[flagLength];
+ for (int n = 0; n < flagLength; ++n) {
+ short same = (short) ((g.flags[n] & 0x10) != 0 ? 1 : -1);
+ if ((g.flags[n] & 0x02) != 0) {
+ g.xCoordinates[n] = (short) (same * fontReader.ReadUInt8());
+ } else {
+ g.xCoordinates[n] = same == 1 ? (short) 0 : fontReader.ReadInt16();
+ }
+ }
+ // 获取轮廓点描述y轴相对值
+ g.yCoordinates = new short[flagLength];
+ for (int n = 0; n < flagLength; ++n) {
+ short same = (short) ((g.flags[n] & 0x20) != 0 ? 1 : -1);
+ if ((g.flags[n] & 0x04) != 0) {
+ g.yCoordinates[n] = (short) (same * fontReader.ReadUInt8());
+ } else {
+ g.yCoordinates[n] = same == 1 ? (short) 0 : fontReader.ReadInt16();
+ }
+ }
+ /* 相对坐标转绝对坐标
+ for (int n = 1; n < flagLength; ++n) {
+ xCoordinates[n] += xCoordinates[n - 1];
+ yCoordinates[n] += yCoordinates[n - 1];
+ }*/
+ glyf.add(g);
+ } else {
+ // 复合字体暂未使用
+ }
+ }
+ }
+ }
+
+ // 建立Unicode&Glyph双向表
+ for (int key = 0; key < 130000; ++key) {
+ if (key == 0xFF) key = 0x3400;
+ int gid = getGlyfIndex(key);
+ if (gid == 0) continue;
+ StringBuilder sb = new StringBuilder();
+ // 字型数据转String,方便存HashMap
+ for (short b : glyf.get(gid).xCoordinates) sb.append(b);
+ for (short b : glyf.get(gid).yCoordinates) sb.append(b);
+ String val = sb.toString();
+ if (limitMix == 0) limitMix = key;
+ limitMax = key;
+ codeToGlyph.put(key, val);
+ if (glyphToCode.containsKey(val)) continue;
+ glyphToCode.put(val, key);
+ }
+ }
+
+ /**
+ * 获取字体信息 (1=字体名称)
+ *
+ * @param nameId 传入十进制字体信息索引
+ * @return 返回查询结果字符串
+ */
+ public String getNameById(int nameId) {
+ for (Directory Temp : directorys) {
+ if (!Temp.tag.equals("name")) continue;
+ fontReader.index = Temp.offset;
+ break;
+ }
+ for (NameRecord record : name.records) {
+ if (record.nameID != nameId) continue;
+ fontReader.index += name.stringOffset + record.offset;
+ return fontReader.ReadStrings(record.length, record.platformID == 1 ? StandardCharsets.UTF_8 : StandardCharsets.UTF_16BE);
+ }
+ return "error";
+ }
+
+ /**
+ * 使用Unicode值查找轮廓索引
+ *
+ * @param code 传入Unicode十进制值
+ * @return 返回十进制轮廓索引
+ */
+ private int getGlyfIndex(int code) {
+ if (code == 0) return 0;
+ int fmtKey = 0;
+ for (Pair item : pps) {
+ for (CmapRecord record : Cmap.records) {
+ if ((item.getLeft() == record.platformID) && (item.getRight() == record.encodingID)) {
+ fmtKey = record.offset;
+ break;
+ }
+ }
+ if (fmtKey > 0) break;
+ }
+ if (fmtKey == 0) return 0;
+
+ int glyfID = 0;
+ CmapFormat table = Cmap.tables.get(fmtKey);
+ assert table != null;
+ int fmt = table.format;
+ if (fmt == 0) {
+ if (code < table.glyphIdArray.length) glyfID = table.glyphIdArray[code] & 0xFF;
+ } else if (fmt == 4) {
+ CmapFormat4 tab = (CmapFormat4) table;
+ if (code > tab.endCode[tab.endCode.length - 1]) return 0;
+ // 二分法查找数值索引
+ int start = 0, middle, end = tab.endCode.length - 1;
+ while (start + 1 < end) {
+ middle = (start + end) / 2;
+ if (tab.endCode[middle] <= code) start = middle;
+ else end = middle;
+ }
+ if (tab.endCode[start] < code) ++start;
+ if (code < tab.startCode[start]) return 0;
+ if (tab.idRangeOffset[start] != 0) {
+ glyfID = tab.glyphIdArray[code - tab.startCode[start] + (tab.idRangeOffset[start] >> 1) - (tab.idRangeOffset.length - start)];
+ } else glyfID = code + tab.idDelta[start];
+ glyfID &= 0xFFFF;
+ } else if (fmt == 6) {
+ CmapFormat6 tab = (CmapFormat6) table;
+ int index = code - tab.firstCode;
+ if (index < 0 || index >= tab.glyphIdArray.length) glyfID = 0;
+ else glyfID = tab.glyphIdArray[index];
+ } else if (fmt == 12) {
+ CmapFormat12 tab = (CmapFormat12) table;
+ if (code > tab.groups.get(tab.numGroups - 1).getMiddle()) return 0;
+ // 二分法查找数值索引
+ int start = 0, middle, end = tab.numGroups - 1;
+ while (start + 1 < end) {
+ middle = (start + end) / 2;
+ if (tab.groups.get(middle).getLeft() <= code) start = middle;
+ else end = middle;
+ }
+ if (tab.groups.get(start).getLeft() <= code && code <= tab.groups.get(start).getMiddle()) {
+ glyfID = tab.groups.get(start).getRight() + code - tab.groups.get(start).getLeft();
+ }
+ }
+ return glyfID;
+ }
+
+ /**
+ * 判断Unicode值是否在字体范围内
+ *
+ * @param code 传入Unicode十进制值
+ * @return 返回bool查询结果
+ */
+ public boolean inLimit(char code) {
+ return (limitMix <= code) && (code < limitMax);
+ }
+
+ /**
+ * 使用Unicode值获取轮廓数据
+ *
+ * @param key 传入Unicode十进制值
+ * @return 返回轮廓数组的String值
+ */
+ public String getGlyfByCode(int key) {
+ return codeToGlyph.getOrDefault(key, "");
+ }
+
+ /**
+ * 使用轮廓数据获取Unicode值
+ *
+ * @param val 传入轮廓数组的String值
+ * @return 返回Unicode十进制值
+ */
+ public int getCodeByGlyf(String val) {
+ //noinspection ConstantConditions
+ return glyphToCode.getOrDefault(val, 0);
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleAnalyzer.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleAnalyzer.kt
new file mode 100644
index 0000000..04576b9
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleAnalyzer.kt
@@ -0,0 +1,396 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+//通用的规则切分处理
+class RuleAnalyzer(data: String, code: Boolean = false) {
+
+ private var queue: String = data //被处理字符串
+ private var pos = 0 //当前处理到的位置
+ private var start = 0 //当前处理字段的开始
+ private var startX = 0 //当前规则的开始
+
+ private var rule = ArrayList() //分割出的规则列表
+ private var step: Int = 0 //分割字符的长度
+ var elementsType = "" //当前分割字符串
+
+ fun trim() { // 修剪当前规则之前的"@"或者空白符
+ if (queue[pos] == '@' || queue[pos] < '!') { //在while里重复设置start和startX会拖慢执行速度,所以先来个判断是否存在需要修剪的字段,最后再一次性设置start和startX
+ pos++
+ while (queue[pos] == '@' || queue[pos] < '!') pos++
+ start = pos //开始点推移
+ startX = pos //规则起始点推移
+ }
+ }
+
+ //将pos重置为0,方便复用
+ fun reSetPos() {
+ pos = 0
+ startX = 0
+ }
+
+ /**
+ * 从剩余字串中拉出一个字符串,直到但不包括匹配序列
+ * @param seq 查找的字符串 **区分大小写**
+ * @return 是否找到相应字段。
+ */
+ private fun consumeTo(seq: String): Boolean {
+ start = pos //将处理到的位置设置为规则起点
+ val offset = queue.indexOf(seq, pos)
+ return if (offset != -1) {
+ pos = offset
+ true
+ } else false
+ }
+
+ /**
+ * 从剩余字串中拉出一个字符串,直到但不包括匹配序列(匹配参数列表中一项即为匹配),或剩余字串用完。
+ * @param seq 匹配字符串序列
+ * @return 成功返回true并设置间隔,失败则直接返回fasle
+ */
+ private fun consumeToAny(vararg seq: String): Boolean {
+
+ var pos = pos //声明新变量记录匹配位置,不更改类本身的位置
+
+ while (pos != queue.length) {
+
+ for (s in seq) {
+ if (queue.regionMatches(pos, s, 0, s.length)) {
+ step = s.length //间隔数
+ this.pos = pos //匹配成功, 同步处理位置到类
+ return true //匹配就返回 true
+ }
+ }
+
+ pos++ //逐个试探
+ }
+ return false
+ }
+
+ /**
+ * 从剩余字串中拉出一个字符串,直到但不包括匹配序列(匹配参数列表中一项即为匹配),或剩余字串用完。
+ * @param seq 匹配字符序列
+ * @return 返回匹配位置
+ */
+ private fun findToAny(vararg seq: Char): Int {
+
+ var pos = pos //声明新变量记录匹配位置,不更改类本身的位置
+
+ while (pos != queue.length) {
+
+ for (s in seq) if (queue[pos] == s) return pos //匹配则返回位置
+
+ pos++ //逐个试探
+
+ }
+
+ return -1
+ }
+
+ /**
+ * 拉出一个非内嵌代码平衡组,存在转义文本
+ */
+ private fun chompCodeBalanced(open: Char, close: Char): Boolean {
+
+ var pos = pos //声明临时变量记录匹配位置,匹配成功后才同步到类的pos
+
+ var depth = 0 //嵌套深度
+ var otherDepth = 0 //其他对称符合嵌套深度
+
+ var inSingleQuote = false //单引号
+ var inDoubleQuote = false //双引号
+
+ do {
+ if (pos == queue.length) break
+ val c = queue[pos++]
+ if (c != ESC) { //非转义字符
+ if (c == '\'' && !inDoubleQuote) inSingleQuote = !inSingleQuote //匹配具有语法功能的单引号
+ else if (c == '"' && !inSingleQuote) inDoubleQuote = !inDoubleQuote //匹配具有语法功能的双引号
+
+ if (inSingleQuote || inDoubleQuote) continue //语法单元未匹配结束,直接进入下个循环
+
+ if (c == '[') depth++ //开始嵌套一层
+ else if (c == ']') depth-- //闭合一层嵌套
+ else if (depth == 0) {
+ //处于默认嵌套中的非默认字符不需要平衡,仅depth为0时默认嵌套全部闭合,此字符才进行嵌套
+ if (c == open) otherDepth++
+ else if (c == close) otherDepth--
+ }
+
+ } else pos++
+
+ } while (depth > 0 || otherDepth > 0) //拉出一个平衡字串
+
+ return if (depth > 0 || otherDepth > 0) false else {
+ this.pos = pos //同步位置
+ true
+ }
+ }
+
+ /**
+ * 拉出一个规则平衡组,经过仔细测试xpath和jsoup中,引号内转义字符无效。
+ */
+ private fun chompRuleBalanced(open: Char, close: Char): Boolean {
+
+ var pos = pos //声明临时变量记录匹配位置,匹配成功后才同步到类的pos
+ var depth = 0 //嵌套深度
+ var inSingleQuote = false //单引号
+ var inDoubleQuote = false //双引号
+
+ do {
+ if (pos == queue.length) break
+ val c = queue[pos++]
+ if (c == '\'' && !inDoubleQuote) inSingleQuote = !inSingleQuote //匹配具有语法功能的单引号
+ else if (c == '"' && !inSingleQuote) inDoubleQuote = !inDoubleQuote //匹配具有语法功能的双引号
+
+ if (inSingleQuote || inDoubleQuote) continue //语法单元未匹配结束,直接进入下个循环
+ else if (c == '\\') { //不在引号中的转义字符才将下个字符转义
+ pos++
+ continue
+ }
+
+ if (c == open) depth++ //开始嵌套一层
+ else if (c == close) depth-- //闭合一层嵌套
+
+ } while (depth > 0) //拉出一个平衡字串
+
+ return if (depth > 0) false else {
+ this.pos = pos //同步位置
+ true
+ }
+ }
+
+ /**
+ * 不用正则,不到最后不切片也不用中间变量存储,只在序列中标记当前查找字段的开头结尾,到返回时才切片,高效快速准确切割规则
+ * 解决jsonPath自带的"&&"和"||"与阅读的规则冲突,以及规则正则或字符串中包含"&&"、"||"、"%%"、"@"导致的冲突
+ */
+ tailrec fun splitRule(vararg split: String): ArrayList { //首段匹配,elementsType为空
+
+ if (split.size == 1) {
+ elementsType = split[0] //设置分割字串
+ return if (!consumeTo(elementsType)) {
+ rule += queue.substring(startX)
+ rule
+ } else {
+ step = elementsType.length //设置分隔符长度
+ splitRule()
+ } //递归匹配
+ } else if (!consumeToAny(* split)) { //未找到分隔符
+ rule += queue.substring(startX)
+ return rule
+ }
+
+ val end = pos //记录分隔位置
+ pos = start //重回开始,启动另一种查找
+
+ do {
+ val st = findToAny('[', '(') //查找筛选器位置
+
+ if (st == -1) {
+
+ rule = arrayListOf(queue.substring(startX, end)) //压入分隔的首段规则到数组
+
+ elementsType = queue.substring(end, end + step) //设置组合类型
+ pos = end + step //跳过分隔符
+
+ while (consumeTo(elementsType)) { //循环切分规则压入数组
+ rule += queue.substring(start, pos)
+ pos += step //跳过分隔符
+ }
+
+ rule += queue.substring(pos) //将剩余字段压入数组末尾
+
+ return rule
+ }
+
+ if (st > end) { //先匹配到st1pos,表明分隔字串不在选择器中,将选择器前分隔字串分隔的字段依次压入数组
+
+ rule = arrayListOf(queue.substring(startX, end)) //压入分隔的首段规则到数组
+
+ elementsType = queue.substring(end, end + step) //设置组合类型
+ pos = end + step //跳过分隔符
+
+ while (consumeTo(elementsType) && pos < st) { //循环切分规则压入数组
+ rule += queue.substring(start, pos)
+ pos += step //跳过分隔符
+ }
+
+ return if (pos > st) {
+ startX = start
+ splitRule() //首段已匹配,但当前段匹配未完成,调用二段匹配
+ } else { //执行到此,证明后面再无分隔字符
+ rule += queue.substring(pos) //将剩余字段压入数组末尾
+ rule
+ }
+ }
+
+ pos = st //位置推移到筛选器处
+ val next = if (queue[pos] == '[') ']' else ')' //平衡组末尾字符
+
+ if (!chompBalanced(queue[pos], next)) throw Error(
+ queue.substring(0, start) + "后未平衡"
+ ) //拉出一个筛选器,不平衡则报错
+
+ } while (end > pos)
+
+ start = pos //设置开始查找筛选器位置的起始位置
+
+ return splitRule(* split) //递归调用首段匹配
+ }
+
+ @JvmName("splitRuleNext")
+ private tailrec fun splitRule(): ArrayList { //二段匹配被调用,elementsType非空(已在首段赋值),直接按elementsType查找,比首段采用的方式更快
+
+ val end = pos //记录分隔位置
+ pos = start //重回开始,启动另一种查找
+
+ do {
+ val st = findToAny('[', '(') //查找筛选器位置
+
+ if (st == -1) {
+
+ rule += arrayOf(queue.substring(startX, end)) //压入分隔的首段规则到数组
+ pos = end + step //跳过分隔符
+
+ while (consumeTo(elementsType)) { //循环切分规则压入数组
+ rule += queue.substring(start, pos)
+ pos += step //跳过分隔符
+ }
+
+ rule += queue.substring(pos) //将剩余字段压入数组末尾
+
+ return rule
+ }
+
+ if (st > end) { //先匹配到st1pos,表明分隔字串不在选择器中,将选择器前分隔字串分隔的字段依次压入数组
+
+ rule += arrayListOf(queue.substring(startX, end)) //压入分隔的首段规则到数组
+ pos = end + step //跳过分隔符
+
+ while (consumeTo(elementsType) && pos < st) { //循环切分规则压入数组
+ rule += queue.substring(start, pos)
+ pos += step //跳过分隔符
+ }
+
+ return if (pos > st) {
+ startX = start
+ splitRule() //首段已匹配,但当前段匹配未完成,调用二段匹配
+ } else { //执行到此,证明后面再无分隔字符
+ rule += queue.substring(pos) //将剩余字段压入数组末尾
+ rule
+ }
+ }
+
+ pos = st //位置推移到筛选器处
+ val next = if (queue[pos] == '[') ']' else ')' //平衡组末尾字符
+
+ if (!chompBalanced(queue[pos], next)) throw Error(
+ queue.substring(0, start) + "后未平衡"
+ ) //拉出一个筛选器,不平衡则报错
+
+ } while (end > pos)
+
+ start = pos //设置开始查找筛选器位置的起始位置
+
+ return if (!consumeTo(elementsType)) {
+ rule += queue.substring(startX)
+ rule
+ } else splitRule() //递归匹配
+
+ }
+
+ /**
+ * 替换内嵌规则
+ * @param inner 起始标志,如{$.
+ * @param startStep 不属于规则部分的前置字符长度,如{$.中{不属于规则的组成部分,故startStep为1
+ * @param endStep 不属于规则部分的后置字符长度
+ * @param fr 查找到内嵌规则时,用于解析的函数
+ *
+ * */
+ fun innerRule(
+ inner: String,
+ startStep: Int = 1,
+ endStep: Int = 1,
+ fr: (String) -> String?
+ ): String {
+ val st = StringBuilder()
+
+ while (consumeTo(inner)) { //拉取成功返回true,ruleAnalyzes里的字符序列索引变量pos后移相应位置,否则返回false,且isEmpty为true
+ val posPre = pos //记录consumeTo匹配位置
+ if (chompCodeBalanced('{', '}')) {
+ val frv = fr(queue.substring(posPre + startStep, pos - endStep))
+ if (!frv.isNullOrEmpty()) {
+ st.append(queue.substring(startX, posPre) + frv) //压入内嵌规则前的内容,及内嵌规则解析得到的字符串
+ startX = pos //记录下次规则起点
+ continue //获取内容成功,继续选择下个内嵌规则
+ }
+ }
+ pos += inner.length //拉出字段不平衡,inner只是个普通字串,跳到此inner后继续匹配
+ }
+
+ return if (startX == 0) "" else st.apply {
+ append(queue.substring(startX))
+ }.toString()
+ }
+
+ /**
+ * 替换内嵌规则
+ * @param fr 查找到内嵌规则时,用于解析的函数
+ *
+ * */
+ fun innerRule(
+ startStr: String,
+ endStr: String,
+ fr: (String) -> String?
+ ): String {
+
+ val st = StringBuilder()
+ while (consumeTo(startStr)) { //拉取成功返回true,ruleAnalyzes里的字符序列索引变量pos后移相应位置,否则返回false,且isEmpty为true
+ pos += startStr.length //跳过开始字符串
+ val posPre = pos //记录consumeTo匹配位置
+ if (consumeTo(endStr)) {
+ val frv = fr(queue.substring(posPre, pos))
+ st.append(
+ queue.substring(
+ startX,
+ posPre - startStr.length
+ ) + frv
+ ) //压入内嵌规则前的内容,及内嵌规则解析得到的字符串
+ pos += endStr.length //跳过结束字符串
+ startX = pos //记录下次规则起点
+ }
+ }
+
+ return if (startX == 0) queue else st.apply {
+ append(queue.substring(startX))
+ }.toString()
+ }
+
+ //设置平衡组函数,json或JavaScript时设置成chompCodeBalanced,否则为chompRuleBalanced
+ val chompBalanced = if (code) ::chompCodeBalanced else ::chompRuleBalanced
+
+ companion object {
+
+ /**
+ * 转义字符
+ */
+ private const val ESC = '\\'
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleData.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleData.kt
new file mode 100644
index 0000000..3424626
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleData.kt
@@ -0,0 +1,35 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+class RuleData : RuleDataInterface {
+
+ override val variableMap by lazy {
+ hashMapOf()
+ }
+
+ override fun putVariable(key: String, value: String?) {
+ if (value != null) {
+ variableMap[key] = value
+ } else {
+ variableMap.remove(key)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleDataInterface.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleDataInterface.kt
new file mode 100644
index 0000000..ce8c76c
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/RuleDataInterface.kt
@@ -0,0 +1,31 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.analyzeRule
+
+interface RuleDataInterface {
+
+ val variableMap: Map
+
+ fun putVariable(key: String, value: String?)
+
+ fun getVariable(key: String): String? {
+ return variableMap[key]
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/http/BackstageWebView.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/http/BackstageWebView.kt
new file mode 100644
index 0000000..2314efe
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/http/BackstageWebView.kt
@@ -0,0 +1,235 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.http
+
+import android.annotation.SuppressLint
+import android.os.Handler
+import android.os.Looper
+import android.util.AndroidRuntimeException
+import android.webkit.CookieManager
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import kotlinx.coroutines.*
+import org.apache.commons.text.StringEscapeUtils
+import xyz.fycz.myreader.application.App
+import xyz.fycz.myreader.common.APPCONST
+import xyz.fycz.myreader.greendao.service.CookieStore
+import xyz.fycz.myreader.model.third3.NoStackTraceException
+import java.lang.ref.WeakReference
+import kotlin.coroutines.resume
+
+/**
+ * 后台webView
+ */
+class BackstageWebView(
+ private val url: String? = null,
+ private val html: String? = null,
+ private val encode: String? = null,
+ private val tag: String? = null,
+ private val headerMap: Map? = null,
+ private val sourceRegex: String? = null,
+ private val javaScript: String? = null,
+) {
+
+ private val mHandler = Handler(Looper.getMainLooper())
+ private var callback: Callback? = null
+ private var mWebView: WebView? = null
+
+ suspend fun getStrResponse(): StrResponse = suspendCancellableCoroutine { block ->
+ block.invokeOnCancellation {
+ App.getHandler().post {
+ destroy()
+ }
+ }
+ callback = object : Callback() {
+ override fun onResult(response: StrResponse) {
+ if (!block.isCompleted)
+ block.resume(response)
+ }
+
+ override fun onError(error: Throwable) {
+ if (!block.isCompleted)
+ block.cancel(error)
+ }
+ }
+ App.getHandler().post {
+ try {
+ load()
+ } catch (error: Throwable) {
+ block.cancel(error)
+ }
+ }
+ }
+
+ private fun getEncoding(): String {
+ return encode ?: "utf-8"
+ }
+
+ @Throws(AndroidRuntimeException::class)
+ private fun load() {
+ val webView = createWebView()
+ mWebView = webView
+ try {
+ when {
+ !html.isNullOrEmpty() -> if (url.isNullOrEmpty()) {
+ webView.loadData(html, "text/html", getEncoding())
+ } else {
+ webView.loadDataWithBaseURL(url, html, "text/html", getEncoding(), url)
+ }
+ else -> if (headerMap == null) {
+ webView.loadUrl(url!!)
+ } else {
+ webView.loadUrl(url!!, headerMap)
+ }
+ }
+ } catch (e: Exception) {
+ callback?.onError(e)
+ }
+ }
+
+ @SuppressLint("SetJavaScriptEnabled", "JavascriptInterface")
+ private fun createWebView(): WebView {
+ val webView = WebView(App.getmContext())
+ val settings = webView.settings
+ settings.javaScriptEnabled = true
+ settings.domStorageEnabled = true
+ settings.blockNetworkImage = true
+ settings.userAgentString = headerMap?.get(APPCONST.UA_NAME)
+ settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
+ if (sourceRegex.isNullOrEmpty()) {
+ webView.webViewClient = HtmlWebViewClient()
+ } else {
+ webView.webViewClient = SnifferWebClient()
+ }
+ return webView
+ }
+
+ private fun destroy() {
+ mWebView?.destroy()
+ mWebView = null
+ }
+
+ private fun getJs(): String {
+ javaScript?.let {
+ if (it.isNotEmpty()) {
+ return it
+ }
+ }
+ return JS
+ }
+
+ private fun setCookie(url: String) {
+ tag?.let {
+ val cookie = CookieManager.getInstance().getCookie(url)
+ CookieStore.setCookie(it, cookie)
+ }
+ }
+
+ private inner class HtmlWebViewClient : WebViewClient() {
+
+ override fun onPageFinished(view: WebView, url: String) {
+ setCookie(url)
+ val runnable = EvalJsRunnable(view, url, getJs())
+ mHandler.postDelayed(runnable, 1000)
+ }
+
+ }
+
+ private inner class EvalJsRunnable(
+ webView: WebView,
+ private val url: String,
+ private val mJavaScript: String
+ ) : Runnable {
+ var retry = 0
+ private val mWebView: WeakReference = WeakReference(webView)
+ override fun run() {
+ mWebView.get()?.evaluateJavascript(mJavaScript) {
+ if (it.isNotEmpty() && it != "null") {
+ val content = StringEscapeUtils.unescapeJson(it)
+ .replace("^\"|\"$".toRegex(), "")
+ try {
+ val response = StrResponse(url, content)
+ callback?.onResult(response)
+ } catch (e: Exception) {
+ callback?.onError(e)
+ }
+ mHandler.removeCallbacks(this)
+ destroy()
+ return@evaluateJavascript
+ }
+ if (retry > 30) {
+ callback?.onError(NoStackTraceException("js执行超时"))
+ mHandler.removeCallbacks(this)
+ destroy()
+ return@evaluateJavascript
+ }
+ retry++
+ mHandler.removeCallbacks(this)
+ mHandler.postDelayed(this, 1000)
+ }
+ }
+ }
+
+ private inner class SnifferWebClient : WebViewClient() {
+
+ override fun onLoadResource(view: WebView, resUrl: String) {
+ sourceRegex?.let {
+ if (resUrl.matches(it.toRegex())) {
+ try {
+ val response = StrResponse(url!!, resUrl)
+ callback?.onResult(response)
+ } catch (e: Exception) {
+ callback?.onError(e)
+ }
+ destroy()
+ }
+ }
+ }
+
+ override fun onPageFinished(webView: WebView, url: String) {
+ setCookie(url)
+ val js = javaScript
+ if (!js.isNullOrEmpty()) {
+ val runnable = LoadJsRunnable(webView, javaScript)
+ mHandler.postDelayed(runnable, 1000L)
+ }
+ }
+
+ }
+
+ private class LoadJsRunnable(
+ webView: WebView,
+ private val mJavaScript: String?
+ ) : Runnable {
+ private val mWebView: WeakReference = WeakReference(webView)
+ override fun run() {
+ mWebView.get()?.loadUrl("javascript:${mJavaScript ?: ""}")
+ }
+ }
+
+ companion object {
+ const val JS = "document.documentElement.outerHTML"
+ }
+
+ abstract class Callback {
+ abstract fun onResult(response: StrResponse)
+ abstract fun onError(error: Throwable)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/http/HttpHelper.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/http/HttpHelper.kt
new file mode 100644
index 0000000..c7c79a7
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/http/HttpHelper.kt
@@ -0,0 +1,131 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.http
+
+import android.util.Log
+import okhttp3.ConnectionSpec
+import okhttp3.Credentials
+import okhttp3.Interceptor
+import okhttp3.OkHttpClient
+import xyz.fycz.myreader.util.SharedPreUtils
+import java.net.InetSocketAddress
+import java.net.Proxy
+import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.TimeUnit
+
+private val proxyClientCache: ConcurrentHashMap by lazy {
+ ConcurrentHashMap()
+}
+
+val okHttpClient: OkHttpClient by lazy {
+ val specs = arrayListOf(
+ ConnectionSpec.MODERN_TLS,
+ ConnectionSpec.COMPATIBLE_TLS,
+ ConnectionSpec.CLEARTEXT
+ )
+
+ val builder = OkHttpClient.Builder()
+ .connectTimeout(15, TimeUnit.SECONDS)
+ .writeTimeout(15, TimeUnit.SECONDS)
+ .readTimeout(15, TimeUnit.SECONDS)
+ .callTimeout(60, TimeUnit.SECONDS)
+ .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory, SSLHelper.unsafeTrustManager)
+ .retryOnConnectionFailure(true)
+ .hostnameVerifier(SSLHelper.unsafeHostnameVerifier)
+ .connectionSpecs(specs)
+ .followRedirects(true)
+ .followSslRedirects(true)
+ .addInterceptor(Interceptor { chain ->
+ val request = chain.request()
+ .newBuilder()
+ .addHeader("Keep-Alive", "300")
+ .addHeader("Connection", "Keep-Alive")
+ .addHeader("Cache-Control", "no-cache")
+ .build()
+ chain.proceed(request)
+ })
+ /*if (AppConfig.isCronet && CronetLoader.install() && !AppConfig.isGooglePlay) {
+ builder.addInterceptor(CronetInterceptor(null))
+ }*/
+ builder.build()
+}
+
+val globalProxy: String
+ get() {
+ val enableProxy = SharedPreUtils.getInstance().getBoolean("enableProxy")
+ if (!enableProxy) {
+ return ""
+ }
+ val type = if (SharedPreUtils.getInstance().getInt("proxyType") == 0) {
+ "http"
+ } else {
+ "socks5"
+ }
+ val host = SharedPreUtils.getInstance().getString("proxyHost")
+ val port = SharedPreUtils.getInstance().getString("proxyPort")
+ val username = SharedPreUtils.getInstance().getString("proxyUsername")
+ val password = SharedPreUtils.getInstance().getString("proxyPassword")
+ return "$type://$host:$port@$username@$password"
+ }
+
+/**
+ * 缓存代理okHttp
+ */
+fun getProxyClient(proxy0: String? = null, noProxy: Boolean = false): OkHttpClient {
+ var proxy = proxy0
+ if (proxy.isNullOrEmpty()) proxy = globalProxy
+ if (proxy.isNullOrBlank() || noProxy) {
+ return okHttpClient
+ }
+ proxyClientCache[proxy]?.let {
+ return it
+ }
+ val r = Regex("(http|socks4|socks5)://(.*):(\\d{2,5})(@.*@.*)?")
+ val ms = r.findAll(proxy)
+ val group = ms.first()
+ var username = "" //代理服务器验证用户名
+ var password = "" //代理服务器验证密码
+ val type = if (group.groupValues[1] == "http") "http" else "socks"
+ val host = group.groupValues[2]
+ val port = group.groupValues[3].toInt()
+ if (group.groupValues[4] != "") {
+ username = group.groupValues[4].split("@")[1]
+ password = group.groupValues[4].split("@")[2]
+ }
+ if (type != "direct" && host != "") {
+ val builder = okHttpClient.newBuilder()
+ if (type == "http") {
+ builder.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress(host, port)))
+ } else {
+ builder.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress(host, port)))
+ }
+ if (username != "" && password != "") {
+ builder.proxyAuthenticator { _, response -> //设置代理服务器账号密码
+ val credential: String = Credentials.basic(username, password)
+ response.request.newBuilder()
+ .header("Proxy-Authorization", credential)
+ .build()
+ }
+ }
+ val proxyClient = builder.build()
+ proxyClientCache[proxy] = proxyClient
+ return proxyClient
+ }
+ return okHttpClient
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/http/OkHttpUtils.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/http/OkHttpUtils.kt
new file mode 100644
index 0000000..c4f49e9
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/http/OkHttpUtils.kt
@@ -0,0 +1,204 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.http
+
+import kotlinx.coroutines.Dispatchers.IO
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.withContext
+import okhttp3.*
+import okhttp3.HttpUrl.Companion.toHttpUrl
+import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.RequestBody.Companion.asRequestBody
+import okhttp3.RequestBody.Companion.toRequestBody
+import xyz.fycz.myreader.common.APPCONST
+import xyz.fycz.myreader.util.help.UTF8BOMFighter
+import xyz.fycz.myreader.util.utils.EncodingDetect
+import xyz.fycz.myreader.util.utils.GSON
+import java.io.File
+import java.io.IOException
+import java.nio.charset.Charset
+import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
+
+suspend fun OkHttpClient.newCallResponse(
+ retry: Int = 0,
+ builder: Request.Builder.() -> Unit
+): Response {
+ return withContext(IO) {
+ val requestBuilder = Request.Builder()
+ requestBuilder.header(APPCONST.UA_NAME, APPCONST.DEFAULT_USER_AGENT)
+ requestBuilder.apply(builder)
+ var response: Response? = null
+ for (i in 0..retry) {
+ response = this@newCallResponse.newCall(requestBuilder.build()).await()
+ if (response.isSuccessful) {
+ return@withContext response
+ }
+ }
+ return@withContext response!!
+ }
+}
+
+suspend fun OkHttpClient.newCallResponseBody(
+ retry: Int = 0,
+ builder: Request.Builder.() -> Unit
+): ResponseBody {
+ return withContext(IO) {
+ val requestBuilder = Request.Builder()
+ requestBuilder.header(APPCONST.UA_NAME, APPCONST.DEFAULT_USER_AGENT)
+ requestBuilder.apply(builder)
+ var response: Response? = null
+ for (i in 0..retry) {
+ response = this@newCallResponseBody.newCall(requestBuilder.build()).await()
+ if (response.isSuccessful) {
+ return@withContext response.body!!
+ }
+ }
+ return@withContext response!!.body ?: throw IOException(response.message)
+ }
+}
+
+suspend fun OkHttpClient.newCallStrResponse(
+ retry: Int = 0,
+ builder: Request.Builder.() -> Unit
+): StrResponse {
+ return withContext(IO) {
+ val requestBuilder = Request.Builder()
+ requestBuilder.header(APPCONST.UA_NAME, APPCONST.DEFAULT_USER_AGENT)
+ requestBuilder.apply(builder)
+ var response: Response? = null
+ for (i in 0..retry) {
+ response = this@newCallStrResponse.newCall(requestBuilder.build()).await()
+ if (response.isSuccessful) {
+ return@withContext StrResponse(response, response.body!!.text())
+ }
+ }
+ return@withContext StrResponse(response!!, response.body?.text() ?: response.message)
+ }
+}
+
+suspend fun Call.await(): Response = suspendCancellableCoroutine { block ->
+
+ block.invokeOnCancellation {
+ cancel()
+ }
+
+ enqueue(object : Callback {
+ override fun onFailure(call: Call, e: IOException) {
+ block.resumeWithException(e)
+ }
+
+ override fun onResponse(call: Call, response: Response) {
+ block.resume(response)
+ }
+ })
+
+}
+
+fun ResponseBody.text(encode: String? = null): String {
+ val responseBytes = UTF8BOMFighter.removeUTF8BOM(bytes())
+ var charsetName: String? = encode
+
+ charsetName?.let {
+ return String(responseBytes, Charset.forName(charsetName))
+ }
+
+ //根据http头判断
+ contentType()?.charset()?.let {
+ return String(responseBytes, it)
+ }
+
+ //根据内容判断
+ charsetName = EncodingDetect.getEncodeInHtml(responseBytes)
+ return String(responseBytes, Charset.forName(charsetName))
+}
+
+fun Request.Builder.addHeaders(headers: Map) {
+ headers.forEach {
+ if (it.key == APPCONST.UA_NAME) {
+ //防止userAgent重复
+ removeHeader(APPCONST.UA_NAME)
+ }
+ addHeader(it.key, it.value)
+ }
+}
+
+fun Request.Builder.get(url: String, queryMap: Map, encoded: Boolean = false) {
+ val httpBuilder = url.toHttpUrl().newBuilder()
+ queryMap.forEach {
+ if (encoded) {
+ httpBuilder.addEncodedQueryParameter(it.key, it.value)
+ } else {
+ httpBuilder.addQueryParameter(it.key, it.value)
+ }
+ }
+ url(httpBuilder.build())
+}
+
+fun Request.Builder.postForm(form: Map, encoded: Boolean = false) {
+ val formBody = FormBody.Builder()
+ form.forEach {
+ if (encoded) {
+ formBody.addEncoded(it.key, it.value.toString())
+ } else {
+ formBody.add(it.key, it.value.toString())
+ }
+ }
+ post(formBody.build())
+}
+
+fun Request.Builder.postMultipart(type: String?, form: Map) {
+ val multipartBody = MultipartBody.Builder()
+ type?.let {
+ multipartBody.setType(type.toMediaType())
+ }
+ form.forEach {
+ when (val value = it.value) {
+ is Map<*, *> -> {
+ val fileName = value["fileName"] as String
+ val file = value["file"]
+ val mediaType = (value["contentType"] as? String)?.toMediaType()
+ val requestBody = when (file) {
+ is File -> {
+ file.asRequestBody(mediaType)
+ }
+ is ByteArray -> {
+ file.toRequestBody(mediaType)
+ }
+ is String -> {
+ file.toRequestBody(mediaType)
+ }
+ else -> {
+ GSON.toJson(file).toRequestBody(mediaType)
+ }
+ }
+ multipartBody.addFormDataPart(it.key, fileName, requestBody)
+ }
+ else -> multipartBody.addFormDataPart(it.key, it.value.toString())
+ }
+ }
+ post(multipartBody.build())
+}
+
+fun Request.Builder.postJson(json: String?) {
+ json?.let {
+ val requestBody = json.toRequestBody("application/json; charset=UTF-8".toMediaType())
+ post(requestBody)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/http/RequestMethod.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/http/RequestMethod.kt
new file mode 100644
index 0000000..ae21e46
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/http/RequestMethod.kt
@@ -0,0 +1,23 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.http
+
+enum class RequestMethod {
+ GET, POST
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/model/third3/http/SSLHelper.kt b/app/src/main/java/xyz/fycz/myreader/model/third3/http/SSLHelper.kt
new file mode 100644
index 0000000..70164d4
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/model/third3/http/SSLHelper.kt
@@ -0,0 +1,202 @@
+/*
+ * This file is part of FYReader.
+ * FYReader is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * FYReader is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FYReader. If not, see .
+ *
+ * Copyright (C) 2020 - 2022 fengyuecanzhu
+ */
+
+package xyz.fycz.myreader.model.third3.http
+
+import android.annotation.SuppressLint
+import android.util.Log
+
+import java.io.IOException
+import java.io.InputStream
+import java.security.KeyManagementException
+import java.security.KeyStore
+import java.security.NoSuchAlgorithmException
+import java.security.SecureRandom
+import java.security.cert.CertificateException
+import java.security.cert.CertificateFactory
+import java.security.cert.X509Certificate
+import javax.net.ssl.*
+
+@Suppress("unused")
+object SSLHelper {
+ private val TAG = SSLHelper::class.simpleName
+ /**
+ * 为了解决客户端不信任服务器数字证书的问题,
+ * 网络上大部分的解决方案都是让客户端不对证书做任何检查,
+ * 这是一种有很大安全漏洞的办法
+ */
+ val unsafeTrustManager: X509TrustManager =
+ @SuppressLint("CustomX509TrustManager")
+ object : X509TrustManager {
+ @SuppressLint("TrustAllX509TrustManager")
+ @Throws(CertificateException::class)
+ override fun checkClientTrusted(chain: Array, authType: String) {
+ //do nothing,接受任意客户端证书
+ }
+
+ @SuppressLint("TrustAllX509TrustManager")
+ @Throws(CertificateException::class)
+ override fun checkServerTrusted(chain: Array, authType: String) {
+ //do nothing,接受任意客户端证书
+ }
+
+ override fun getAcceptedIssuers(): Array {
+ return arrayOf()
+ }
+ }
+
+ val unsafeSSLSocketFactory: SSLSocketFactory by lazy {
+ try {
+ val sslContext = SSLContext.getInstance("SSL")
+ sslContext.init(null, arrayOf(unsafeTrustManager), SecureRandom())
+ sslContext.socketFactory
+ } catch (e: Exception) {
+ throw RuntimeException(e)
+ }
+ }
+
+ /**
+ * 此类是用于主机名验证的基接口。 在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,
+ * 则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。策略可以是基于证书的或依赖于其他验证方案。
+ * 当验证 URL 主机名使用的默认规则失败时使用这些回调。如果主机名是可接受的,则返回 true
+ */
+ val unsafeHostnameVerifier: HostnameVerifier = HostnameVerifier { _, _ -> true }
+
+ class SSLParams {
+ lateinit var sSLSocketFactory: SSLSocketFactory
+ lateinit var trustManager: X509TrustManager
+ }
+
+ /**
+ * https单向认证
+ * 可以额外配置信任服务端的证书策略,否则默认是按CA证书去验证的,若不是CA可信任的证书,则无法通过验证
+ */
+ fun getSslSocketFactory(trustManager: X509TrustManager): SSLParams? {
+ return getSslSocketFactoryBase(trustManager, null, null)
+ }
+
+ /**
+ * https单向认证
+ * 用含有服务端公钥的证书校验服务端证书
+ */
+ fun getSslSocketFactory(vararg certificates: InputStream): SSLParams? {
+ return getSslSocketFactoryBase(null, null, null, *certificates)
+ }
+
+ /**
+ * https双向认证
+ * bksFile 和 password -> 客户端使用bks证书校验服务端证书
+ * certificates -> 用含有服务端公钥的证书校验服务端证书
+ */
+ fun getSslSocketFactory(
+ bksFile: InputStream,
+ password: String,
+ vararg certificates: InputStream
+ ): SSLParams? {
+ return getSslSocketFactoryBase(null, bksFile, password, *certificates)
+ }
+
+ /**
+ * https双向认证
+ * bksFile 和 password -> 客户端使用bks证书校验服务端证书
+ * X509TrustManager -> 如果需要自己校验,那么可以自己实现相关校验,如果不需要自己校验,那么传null即可
+ */
+ fun getSslSocketFactory(
+ bksFile: InputStream,
+ password: String,
+ trustManager: X509TrustManager
+ ): SSLParams? {
+ return getSslSocketFactoryBase(trustManager, bksFile, password)
+ }
+
+ private fun getSslSocketFactoryBase(
+ trustManager: X509TrustManager?,
+ bksFile: InputStream?,
+ password: String?,
+ vararg certificates: InputStream
+ ): SSLParams? {
+ val sslParams = SSLParams()
+ try {
+ val keyManagers = prepareKeyManager(bksFile, password)
+ val trustManagers = prepareTrustManager(*certificates)
+ val manager: X509TrustManager = trustManager ?: chooseTrustManager(trustManagers)
+ // 创建TLS类型的SSLContext对象, that uses our TrustManager
+ val sslContext = SSLContext.getInstance("TLS")
+ // 用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书
+ // 第一个参数是授权的密钥管理器,用来授权验证,比如授权自签名的证书验证。第二个是被授权的证书管理器,用来验证服务器端的证书
+ sslContext.init(keyManagers, arrayOf