Skip to content

Commit 712fdfe

Browse files
author
SkyD666
committed
[feature]支持DoH;此版本不再内置默认数据源,使用此APP需手动选择自定义数据源
1 parent e3af1c8 commit 712fdfe

82 files changed

Lines changed: 1683 additions & 1037 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.idea/misc.xml

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
----
2929

30+
## [>>自定义数据源<<](doc/customdatasource/README.md)
31+
3032
## [>>必看安全说明<<](#安全说明)
3133

3234
## [>>关于http网站或数据源的安全问题<<](doc/about_http_security.md)

app/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ android.defaultConfig {
1616
secret.shieldTextList.forEach({ k, v ->
1717
buildConfigField("String[]", k, v)
1818
})
19+
secret.dataSource.forEach({ k, v ->
20+
buildConfigField("String", k, "\"${v}\"")
21+
})
1922
}
2023

2124
android {
@@ -147,6 +150,7 @@ dependencies {
147150
implementation deps.kotlinx.kotlinx_coroutines_android
148151
implementation deps.material_dialogs.core
149152
implementation deps.material_dialogs.input
153+
implementation deps.material_dialogs.files
150154
implementation deps.room.room_runtime
151155
implementation deps.room.room_ktx
152156
kapt deps.room.room_compiler
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.skyd.imomoe.bean
2+
3+
import com.google.gson.annotations.SerializedName
4+
import java.io.Serializable
5+
6+
class DoHJsonBean(
7+
override var type: String = "",
8+
override var actionUrl: String = "",
9+
@SerializedName("Status")
10+
var status: Int,
11+
@SerializedName("TC")
12+
var tc: Boolean,
13+
@SerializedName("RD")
14+
var rd: Boolean,
15+
@SerializedName("RA")
16+
var ra: Boolean,
17+
@SerializedName("AD")
18+
var ad: Boolean,
19+
@SerializedName("CD")
20+
var cd: Boolean,
21+
@SerializedName("Question")
22+
var question: List<Question>,
23+
@SerializedName("Answer")
24+
var answer: List<Answer>?,
25+
@SerializedName("Comment")
26+
var comment: String?,
27+
@SerializedName("edns_client_subnet")
28+
var eDNSClientSubnet: String?
29+
) : BaseBean {
30+
class Question(
31+
@SerializedName("name")
32+
var name: String,
33+
@SerializedName("type")
34+
var type: Int
35+
) : Serializable
36+
37+
class Answer(
38+
@SerializedName("name")
39+
var name: String,
40+
@SerializedName("type")
41+
var type: Int,
42+
@SerializedName("TTL")
43+
var ttl: Int,
44+
@SerializedName("data")
45+
var data: String
46+
) : Serializable
47+
}

app/src/main/java/com/skyd/imomoe/config/Api.kt

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,16 @@ import com.skyd.imomoe.model.DataSourceManager
44

55
interface Api {
66
companion object {
7-
const val DEFAULT_MAIN_URL = "http://www.yhdm.io"
8-
var MAIN_URL = DEFAULT_MAIN_URL
9-
get() = (DataSourceManager.getConst() ?: com.skyd.imomoe.model.impls.Const())
10-
.MAIN_URL()
11-
// return App.context.sharedPreferences("url")
12-
// .getString("mainUrl", DEFAULT_MAIN_URL) ?: DEFAULT_MAIN_URL
13-
private set/*(value) {
14-
App.context.sharedPreferences("url").editor {
15-
putString("mainUrl", value)
16-
}
17-
}*/
7+
val MAIN_URL
8+
get() = (DataSourceManager.getConst() ?: com.skyd.imomoe.model.impls.Const()).MAIN_URL()
189

19-
//github
10+
// github
2011
const val CHECK_UPDATE_URL = "https://api.github.com/repos/SkyD666/Imomoe/releases/latest"
2112

22-
//弹幕url
13+
// 弹幕url
2314
const val DANMU_URL = "https://yuan.cuan.la/barrage/api"
2415

16+
// DoH
17+
const val DOH_URL = "https://1.0.0.1/dns-query"
2518
}
2619
}

app/src/main/java/com/skyd/imomoe/config/Const.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ interface Const {
1010
const val GITHUB_URL = "https://github.com/SkyD666/Imomoe"
1111
const val GITHUB_NEW_ISSUE_URL = "https://github.com/SkyD666/Imomoe/issues/new"
1212
const val USER_NOTICE_VERSION = 1
13+
const val DNS_OVER_HTTPS = "https://1.0.0.1/dns-query"
1314
}
1415
}
1516

app/src/main/java/com/skyd/imomoe/model/DataSourceManager.kt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,46 @@ import com.skyd.imomoe.BuildConfig
77
import com.skyd.imomoe.model.interfaces.IConst
88
import com.skyd.imomoe.model.interfaces.IRouteProcessor
99
import com.skyd.imomoe.model.interfaces.IUtil
10+
import com.skyd.imomoe.util.Util.showToast
1011
import com.skyd.imomoe.util.editor
1112
import com.skyd.imomoe.util.sharedPreferences
1213
import dalvik.system.DexClassLoader
1314
import java.io.File
1415

1516

1617
object DataSourceManager {
17-
var useCustomDataSource: Boolean
18+
// var useCustomDataSource: Boolean
19+
// get() {
20+
// return App.context.sharedPreferences().getBoolean("useCustomDataSource", false)
21+
// }
22+
// set(value) {
23+
// App.context.sharedPreferences().editor { putBoolean("useCustomDataSource", value) }
24+
// }
25+
26+
const val DEFAULT_DATA_SOURCE = ""
27+
28+
var dataSourceName: String =
29+
App.context.sharedPreferences().getString("dataSourceName", DEFAULT_DATA_SOURCE)
30+
?: DEFAULT_DATA_SOURCE
1831
get() {
19-
return App.context.sharedPreferences().getBoolean("customDataSource", false)
32+
return if (field.isBlank() && App.context.sharedPreferences()
33+
.getBoolean("customDataSource", false)
34+
) "CustomDataSource.jar" else field
2035
}
2136
set(value) {
22-
App.context.sharedPreferences().editor { putBoolean("customDataSource", value) }
37+
field = value
38+
App.context.sharedPreferences().editor { putString("dataSourceName", value) }
2339
}
2440

2541
// 第一个是传入的接口,第二个是实现类
2642
private val cache: LruCache<Class<*>, Class<*>> = LruCache(10)
2743
private val singletonCache: LruCache<Class<*>, Any> = LruCache(5)
2844

29-
fun getJarPath(): String {
30-
// return "${Environment.getExternalStorageDirectory()}/Download/DataSourceJar/CustomDataSource.jar"
31-
return App.context.getExternalFilesDir(null)
32-
.toString() + "/DataSourceJar/CustomDataSource.jar"
45+
fun getJarPath(): String =
46+
"${getJarDirectory()}/${dataSourceName}"
47+
48+
fun getJarDirectory(): String {
49+
return "${App.context.getExternalFilesDir(null).toString()}/DataSourceJar"
3350
}
3451

3552
fun <T> getBinaryName(clazz: Class<T>): String {
@@ -77,7 +94,7 @@ object DataSourceManager {
7794
@Suppress("UNCHECKED_CAST")
7895
fun <T> create(clazz: Class<T>): T? {
7996
// 如果不使用自定义数据,直接返回null
80-
if (!useCustomDataSource) return null
97+
if (dataSourceName == DEFAULT_DATA_SOURCE) return null
8198
cache[clazz]?.let {
8299
return it.newInstance() as T
83100
}
Lines changed: 1 addition & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,12 @@
11
package com.skyd.imomoe.model.impls
22

33
import com.skyd.imomoe.bean.*
4-
import com.skyd.imomoe.config.Api
5-
import com.skyd.imomoe.config.Const
6-
import com.skyd.imomoe.model.util.JsoupUtil
7-
import com.skyd.imomoe.model.util.ParseHtmlUtil
8-
import com.skyd.imomoe.model.util.ParseHtmlUtil.parseBotit
94
import com.skyd.imomoe.model.interfaces.IAnimeDetailModel
10-
import org.jsoup.select.Elements
115

126
class AnimeDetailModel : IAnimeDetailModel {
137
override suspend fun getAnimeDetailData(
148
partUrl: String
159
): Triple<ImageBean, String, ArrayList<IAnimeDetailBean>> {
16-
val animeDetailList: ArrayList<IAnimeDetailBean> = ArrayList()
17-
val cover = ImageBean("", "", "", "")
18-
var title = ""
19-
val url = Api.MAIN_URL + partUrl
20-
val document = JsoupUtil.getDocument(url)
21-
//番剧头部信息
22-
val area: Elements = document.getElementsByClass("area")
23-
for (i in area.indices) {
24-
val areaChildren = area[i].children()
25-
for (j in areaChildren.indices) {
26-
when (areaChildren[j].className()) {
27-
"fire l" -> {
28-
var alias = ""
29-
var info = ""
30-
var year = ""
31-
var index = ""
32-
var animeArea = ""
33-
val animeType: MutableList<AnimeTypeBean> = ArrayList()
34-
val tag: MutableList<AnimeTypeBean> = ArrayList()
35-
36-
val fireLChildren =
37-
areaChildren[j].select("[class=fire l]")[0].children()
38-
for (k in fireLChildren.indices) {
39-
when (fireLChildren[k].className()) {
40-
"thumb l" -> {
41-
cover.url = fireLChildren[k]
42-
.select("img").attr("src")
43-
cover.referer = url
44-
}
45-
"rate r" -> {
46-
val rateR = fireLChildren[k]
47-
title = rateR.select("h1").text()
48-
val sinfo: Elements = rateR.select("[class=sinfo]")
49-
val span: Elements = sinfo.select("span")
50-
val p: Elements = sinfo.select("p")
51-
if (p.size == 1) {
52-
alias = p[0].text()
53-
} else if (p.size == 2) {
54-
alias = p[0].text()
55-
info = p[1].text()
56-
}
57-
year = span[0].text()
58-
animeArea = span[1].select("a").text()
59-
index = span[3].select("a").text()
60-
val typeElements: Elements = span[2].select("a")
61-
for (l in typeElements.indices) {
62-
animeType.add(
63-
AnimeTypeBean(
64-
"",
65-
typeElements[l].attr("href"),
66-
Api.MAIN_URL + typeElements[l].attr("href"),
67-
typeElements[l].text()
68-
)
69-
)
70-
}
71-
val tagElements: Elements = span[4].select("a")
72-
for (l in tagElements.indices) {
73-
tag.add(
74-
AnimeTypeBean(
75-
"",
76-
tagElements[l].attr("href"),
77-
Api.MAIN_URL + tagElements[l].attr("href"),
78-
tagElements[l].text()
79-
)
80-
)
81-
}
82-
}
83-
"tabs", "tabs noshow" -> { //播放列表+header
84-
animeDetailList.add(
85-
AnimeDetailBean(
86-
Const.ViewHolderTypeString.HEADER_1, "",
87-
fireLChildren[k].select("[class=menu0]")
88-
.select("li").text(),
89-
"",
90-
null
91-
)
92-
)
93-
94-
animeDetailList.add(
95-
AnimeDetailBean(
96-
Const.ViewHolderTypeString.HORIZONTAL_RECYCLER_VIEW_1,
97-
"",
98-
"",
99-
"",
100-
ParseHtmlUtil.parseMovurls(
101-
fireLChildren[k].select("[class=main0]")
102-
.select("[class=movurl]")[0]
103-
)
104-
)
105-
)
106-
}
107-
"botit" -> { //其它header
108-
animeDetailList.add(
109-
AnimeDetailBean(
110-
Const.ViewHolderTypeString.HEADER_1, "",
111-
parseBotit(fireLChildren[k]),
112-
"",
113-
null
114-
)
115-
)
116-
}
117-
"dtit" -> { //其它header
118-
animeDetailList.add(
119-
AnimeDetailBean(
120-
Const.ViewHolderTypeString.HEADER_1, "",
121-
ParseHtmlUtil.parseDtit(fireLChildren[k]),
122-
"",
123-
null
124-
)
125-
)
126-
}
127-
"info" -> { //动漫介绍
128-
animeDetailList.add(
129-
AnimeDetailBean(
130-
Const.ViewHolderTypeString.ANIME_DESCRIBE_1, "",
131-
"",
132-
fireLChildren[k]
133-
.select("[class=info]").text(),
134-
null
135-
)
136-
)
137-
}
138-
"img" -> { //系列动漫推荐
139-
animeDetailList.addAll(
140-
ParseHtmlUtil.parseImg(fireLChildren[k], url)
141-
)
142-
}
143-
}
144-
}
145-
val animeInfoBean = AnimeInfoBean(
146-
"",
147-
"",
148-
title,
149-
ImageBean("", "", cover.url, url),
150-
alias,
151-
animeArea,
152-
year,
153-
index,
154-
animeType,
155-
tag,
156-
info
157-
)
158-
animeDetailList.add(
159-
0,
160-
AnimeDetailBean(
161-
Const.ViewHolderTypeString.ANIME_INFO_1, "",
162-
"",
163-
"",
164-
headerInfo = animeInfoBean
165-
)
166-
)
167-
}
168-
}
169-
}
170-
}
171-
return Triple(cover, title, animeDetailList)
10+
return Triple(ImageBean("", "", "", ""), "", ArrayList())
17211
}
17312
}

0 commit comments

Comments
 (0)