@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty
4
4
import com.fasterxml.jackson.module.kotlin.readValue
5
5
import com.lagradost.quicknovel.*
6
6
import com.lagradost.quicknovel.MainActivity.Companion.app
7
+ import com.lagradost.quicknovel.network.CloudflareKiller
7
8
import org.jsoup.Jsoup
8
9
9
10
class MtlNovelProvider : MainAPI () {
@@ -17,47 +18,48 @@ class MtlNovelProvider : MainAPI() {
17
18
18
19
override val tags = listOf (
19
20
Pair (" All" , " " ),
20
- Pair (" Adult" ," adult" ),
21
- Pair (" Adventure" ," adventure" ),
22
- Pair (" Comedy" ," comedy" ),
23
- Pair (" Drama" ," drama" ),
24
- Pair (" Ecchi" ," ecchi" ),
25
- Pair (" Erciyuan" ," erciyuan" ),
26
- Pair (" Fan-Fiction" ," fan-fiction" ),
27
- Pair (" Fantasy" ," fantasy" ),
28
- Pair (" Game" ," game" ),
29
- Pair (" Gender Bender" ," Gender-Bender" ),
30
- Pair (" Harem" ," harem" ),
31
- Pair (" Historical" ," historical" ),
32
- Pair (" Horror" ," horror" ),
33
- Pair (" Josei" ," josei" ),
34
- Pair (" Martial Arts" ," martial-arts" ),
35
- Pair (" Mature" ," mature" ),
36
- Pair (" Mecha" ," mecha" ),
37
- Pair (" Military" ," military" ),
38
- Pair (" Mystery" ," mystery" ),
39
- Pair (" Psychological" ," psychological" ),
40
- Pair (" Romance" ," romance" ),
41
- Pair (" School Life" ," school-life" ),
42
- Pair (" Sci-fi" ," sci-fi" ),
43
- Pair (" Seinen" ," seinen" ),
44
- Pair (" Shoujo" ," shoujo" ),
45
- Pair (" Shoujo Ai" ," shoujo-ai" ),
46
- Pair (" Shounen" ," shounen" ),
47
- Pair (" Shounen Ai" ," shounen-ai" ),
48
- Pair (" Slice of Life" ," slice-of-life" ),
49
- Pair (" Smut" ," smut" ),
50
- Pair (" Sports" ," sports" ),
51
- Pair (" Supernatural" ," supernatural" ),
52
- Pair (" Tragedy" ," tragedy" ),
53
- Pair (" Two-dimensional" ," two-dimensional" ),
54
- Pair (" Urban Life" ," urban-life" ),
55
- Pair (" Wuxia" ," wuxia" ),
56
- Pair (" Xianxia" ," xianxia" ),
57
- Pair (" Xuanhuan" ," xuanhuan" ),
58
- Pair (" Yaoi" ," yaoi" ),
59
- Pair (" Yuri" ," yuri" ),
21
+ Pair (" Adult" , " adult" ),
22
+ Pair (" Adventure" , " adventure" ),
23
+ Pair (" Comedy" , " comedy" ),
24
+ Pair (" Drama" , " drama" ),
25
+ Pair (" Ecchi" , " ecchi" ),
26
+ Pair (" Erciyuan" , " erciyuan" ),
27
+ Pair (" Fan-Fiction" , " fan-fiction" ),
28
+ Pair (" Fantasy" , " fantasy" ),
29
+ Pair (" Game" , " game" ),
30
+ Pair (" Gender Bender" , " Gender-Bender" ),
31
+ Pair (" Harem" , " harem" ),
32
+ Pair (" Historical" , " historical" ),
33
+ Pair (" Horror" , " horror" ),
34
+ Pair (" Josei" , " josei" ),
35
+ Pair (" Martial Arts" , " martial-arts" ),
36
+ Pair (" Mature" , " mature" ),
37
+ Pair (" Mecha" , " mecha" ),
38
+ Pair (" Military" , " military" ),
39
+ Pair (" Mystery" , " mystery" ),
40
+ Pair (" Psychological" , " psychological" ),
41
+ Pair (" Romance" , " romance" ),
42
+ Pair (" School Life" , " school-life" ),
43
+ Pair (" Sci-fi" , " sci-fi" ),
44
+ Pair (" Seinen" , " seinen" ),
45
+ Pair (" Shoujo" , " shoujo" ),
46
+ Pair (" Shoujo Ai" , " shoujo-ai" ),
47
+ Pair (" Shounen" , " shounen" ),
48
+ Pair (" Shounen Ai" , " shounen-ai" ),
49
+ Pair (" Slice of Life" , " slice-of-life" ),
50
+ Pair (" Smut" , " smut" ),
51
+ Pair (" Sports" , " sports" ),
52
+ Pair (" Supernatural" , " supernatural" ),
53
+ Pair (" Tragedy" , " tragedy" ),
54
+ Pair (" Two-dimensional" , " two-dimensional" ),
55
+ Pair (" Urban Life" , " urban-life" ),
56
+ Pair (" Wuxia" , " wuxia" ),
57
+ Pair (" Xianxia" , " xianxia" ),
58
+ Pair (" Xuanhuan" , " xuanhuan" ),
59
+ Pair (" Yaoi" , " yaoi" ),
60
+ Pair (" Yuri" , " yuri" ),
60
61
)
62
+ val interceptor = CloudflareKiller ()
61
63
62
64
override suspend fun loadMainPage (
63
65
page : Int ,
@@ -69,13 +71,14 @@ class MtlNovelProvider : MainAPI() {
69
71
if (tag.isNullOrBlank()) " $mainUrl /alltime-rank/page/$page " else " $mainUrl /genre/$tag /page/$page "
70
72
71
73
72
- val document = app.get(url).document
74
+ val document = app.get(url, interceptor = interceptor ).document
73
75
74
- val headers = document.select(" div.box" )
76
+ val headers = document.select(" div.box" )
75
77
if (headers.size <= 0 ) return HeadMainPageResponse (url, ArrayList ())
76
78
val returnValue: ArrayList <SearchResponse > = ArrayList ()
77
79
for (h in headers) {
78
- val name = h?.selectFirst(" a" )?.attr(" aria-label" )?.substringBeforeLast(" Cover" ) ? : continue
80
+ val name =
81
+ h?.selectFirst(" a" )?.attr(" aria-label" )?.substringBeforeLast(" Cover" ) ? : continue
79
82
val cUrl = h.selectFirst(" a" )?.attr(" href" ) ? : throw ErrorLoadingException ()
80
83
val posterUrl = h.selectFirst(" amp-img amp-img" )?.attr(" src" )
81
84
returnValue.add(
@@ -93,14 +96,29 @@ class MtlNovelProvider : MainAPI() {
93
96
}
94
97
95
98
override suspend fun loadHtml (url : String ): String? {
96
- return app.get(url).document.selectFirst(" div.par" )?.html()
99
+ return app.get(url, interceptor = interceptor ).document.selectFirst(" div.par" )?.html()
97
100
}
98
101
99
102
100
103
override suspend fun search (query : String ): List <SearchResponse > {
101
104
val response =
102
- SearchResults .fromJson(app.get(" https://www.mtlnovel.com/wp-admin/admin-ajax.php?action=autosuggest&q=$query " ).text)
103
- return response?.items?.first()?.results?.map { SearchResponse (Jsoup .parse(it.title).text(), it.permalink!! , it.thumbnail, null , null , name) }!! }
105
+ SearchResults .fromJson(
106
+ app.get(
107
+ " $mainUrl /wp-admin/admin-ajax.php?action=autosuggest&q=$query " ,
108
+ interceptor = interceptor
109
+ ).text
110
+ )
111
+ return response.items?.first()?.results?.mapNotNull {
112
+ SearchResponse (
113
+ name = Jsoup .parse(it.title ? : return @mapNotNull null ).text(),
114
+ url = it.permalink ? : return @mapNotNull null ,
115
+ it.thumbnail,
116
+ null ,
117
+ null ,
118
+ name
119
+ )
120
+ }!!
121
+ }
104
122
105
123
106
124
override suspend fun load (url : String ): LoadResponse ? {
@@ -119,16 +137,23 @@ class MtlNovelProvider : MainAPI() {
119
137
val synopsis = document.selectFirst(" div.desc" )?.text()
120
138
121
139
val data: ArrayList <ChapterData > = ArrayList ()
122
- val chapters = app.get(url+ " /chapter-list/" ).document.select(" div.ch-list a" ).reversed()
140
+ val chapters = app.get(
141
+ " $url /chapter-list/" ,
142
+ interceptor = interceptor
143
+ ).document.select(" div.ch-list a" ).reversed()
123
144
for (c in chapters) {
124
145
val href = c?.attr(" href" ) ? : continue
125
146
val cName = c.text()
126
147
data.add(ChapterData (cName, href, null , null ))
127
148
128
149
}
129
150
130
- val rating = document.selectFirst(" span.rating-info" )?.selectFirst(" strong" )?.text()?.toFloat()?.times(200 )?.toInt()
131
- val peopleVoted = " \\ ((.+) re" .toRegex().find(document.selectFirst(" span.rating-info" )?.text().toString())?.groupValues?.last()?.toInt()
151
+ val rating =
152
+ document.selectFirst(" span.rating-info" )?.selectFirst(" strong" )?.text()?.toFloat()
153
+ ?.times(200 )?.toInt()
154
+ val peopleVoted = " \\ ((.+) re" .toRegex()
155
+ .find(document.selectFirst(" span.rating-info" )?.text().toString())?.groupValues?.last()
156
+ ?.toInt()
132
157
133
158
134
159
return StreamResponse (
@@ -148,19 +173,20 @@ class MtlNovelProvider : MainAPI() {
148
173
}
149
174
150
175
151
- private data class SearchResults (
176
+ private data class SearchResults (
152
177
@get:JsonProperty("items") val items : List <Item >? = null
153
178
) {
154
179
companion object {
155
180
fun fromJson (json : String ) = mapper.readValue<SearchResults >(json)
156
181
}
157
182
}
158
- private data class Item (
183
+
184
+ private data class Item (
159
185
@get:JsonProperty("query") val query : String? = null ,
160
186
@get:JsonProperty("results") val results : List <Result >? = null
161
187
)
162
188
163
- private data class Result (
189
+ private data class Result (
164
190
@get:JsonProperty("title") val title : String? = null ,
165
191
@get:JsonProperty("permalink") val permalink : String? = null ,
166
192
@get:JsonProperty("thumbnail") val thumbnail : String? = null ,
0 commit comments