From 52d9e842841c8a42f61bd795d0e1d0a3c5d7ca1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E7=BA=A2=E6=9F=BF=E5=A4=A7=E8=8A=9D=E9=BA=BB?= <747455334@qq.com> Date: Fri, 26 Jul 2019 23:24:10 +0800 Subject: [PATCH 01/27] Update gradle-wrapper.properties --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 418447c..1a58ff9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip From 50ebc37796b6df1ebe32074cfd33e36119241da7 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 27 Jul 2019 02:58:15 +0800 Subject: [PATCH 02/27] add source https://www.manhualou.com --- .../rechinx/meow/core/source/SourceManager.kt | 4 +- .../meow/core/source/internal/ManHuaLou.kt | 98 +++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index ae0c8e2..5fefa11 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -2,6 +2,7 @@ package top.rechinx.meow.core.source import android.content.Context import top.rechinx.meow.core.source.internal.Dmzj +import top.rechinx.meow.core.source.internal.ManHuaLou class SourceManager(private val context: Context) { @@ -36,7 +37,8 @@ class SourceManager(private val context: Context) { } private fun createInternalSources(): List = listOf( - Dmzj() + Dmzj(), + ManHuaLou() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt new file mode 100644 index 0000000..3f05644 --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt @@ -0,0 +1,98 @@ +package top.rechinx.meow.core.source.internal + +import okhttp3.Request +import okhttp3.Response +import org.json.JSONArray + +import org.jsoup.Jsoup + +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* + + +class ManHuaLou:HttpSource() { + + override val name: String = "漫画楼" + + override val baseUrl: String = "https://www.manhualou.com" + + + override fun getFilterList(): FilterList { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun imageUrlParse(response: Response): String { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + private fun GET(url: String) = Request.Builder() + .url(url) + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request + = GET("$baseUrl/search/?keywords=$keyword&page=$page") + + override fun searchMangaParse(response: Response): PagedList + = commonMangaParse(response) + + private fun commonMangaParse(response: Response): PagedList { + val res = response.body()!!.string() + val ret = Jsoup.parse(res).select("#contList li").map { node -> SManga.create().apply { + title = node.selectFirst("p").text() + thumbnail_url = node.selectFirst("img").attr("src") + url = node.selectFirst("a").attr("href") + } } + return PagedList(ret, true) + } + override fun popularMangaRequest(page: Int): Request + = GET("$baseUrl/list_$page") + + override fun popularMangaParse(response: Response): PagedList + = commonMangaParse(response) + + override fun mangaInfoRequest(url: String): Request + = GET(url) + + override fun mangaInfoParse(response: Response): SManga + = SManga.create().apply { + val res = response.body()!!.string() + var doc = Jsoup.parse(res) + title = doc.selectFirst(".book-title").text() + thumbnail_url = doc.selectFirst(".cover .pic").attr("src") + author = doc.selectFirst("ul.detail-list.cf > li:nth-of-type(2) > span:nth-of-type(2) > a").text() + status = when(doc.selectFirst(".status a").text()) { + "已完结" -> SManga.COMPLETED + "连载中" -> SManga.ONGOING + else -> SManga.UNKNOWN + } + description = doc.select(".book-intro").last().text() + } + + override fun chaptersRequest(page: Int, url: String): Request + = GET(url) + + override fun chaptersParse(response: Response): PagedList { + val res = response.body()!!.string() + val ret = Jsoup.parse(res).select(".chapter-body.clearfix a").map { node -> SChapter.create().apply { + name = node.text() + url = node.attr("href") + } } + return PagedList(ret, false) + } + + override fun mangaPagesRequest(chapter: SChapter): Request + = GET(baseUrl + chapter.url) + + override fun mangaPagesParse(response: Response): List { + val res = response.body()!!.string() + val arr = JSONArray(Regex("chapterImages\\s*=\\s*([^;]*)").find(res)!!.groupValues[1]) + val ret = ArrayList(arr.length()) + for (i in 0 until arr.length()) { + ret.add(MangaPage(i, "", "https://restp.dongqiniqin.com/"+arr.getString(i))) + } + return ret + } + + +} \ No newline at end of file From 5ae50b47cab02e751a6d32eae089bfcd2c629d7a Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 27 Jul 2019 03:01:02 +0800 Subject: [PATCH 03/27] add source https://www.manhualou.com --- .../java/top/rechinx/meow/core/source/internal/ManHuaLou.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt index 3f05644..59ee993 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt @@ -21,9 +21,7 @@ class ManHuaLou:HttpSource() { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } - override fun imageUrlParse(response: Response): String { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") private fun GET(url: String) = Request.Builder() .url(url) From b0da57cf6b6ddcbfe116701a050013642fc1feb2 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 27 Jul 2019 10:38:35 +0800 Subject: [PATCH 04/27] fix source https://www.manhualou.com --- .../meow/core/source/internal/ManHuaLou.kt | 270 +++++++++++++++++- 1 file changed, 260 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt index 59ee993..e58816e 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt @@ -16,10 +16,8 @@ class ManHuaLou:HttpSource() { override val baseUrl: String = "https://www.manhualou.com" - - override fun getFilterList(): FilterList { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } + override fun getFilterList(): FilterList + = FilterList(Types(), Orgins(), Plots(), Letters(), Progresses()) override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") @@ -28,8 +26,17 @@ class ManHuaLou:HttpSource() { .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") .build() - override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request - = GET("$baseUrl/search/?keywords=$keyword&page=$page") + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request{ + if("" != keyword){ + return GET("$baseUrl/search/?keywords=$keyword&page=$page") + } else{ + val params = filters.map { (it as UriPartFilter).getUrl() }.joinToString("-") + if("" != params){ + return GET("$baseUrl/list/${params}_$page/") + } + return GET("$baseUrl/list_$page/") + } + } override fun searchMangaParse(response: Response): PagedList = commonMangaParse(response) @@ -44,7 +51,7 @@ class ManHuaLou:HttpSource() { return PagedList(ret, true) } override fun popularMangaRequest(page: Int): Request - = GET("$baseUrl/list_$page") + = GET("$baseUrl/list_$page/") override fun popularMangaParse(response: Response): PagedList = commonMangaParse(response) @@ -55,7 +62,7 @@ class ManHuaLou:HttpSource() { override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { val res = response.body()!!.string() - var doc = Jsoup.parse(res) + val doc = Jsoup.parse(res) title = doc.selectFirst(".book-title").text() thumbnail_url = doc.selectFirst(".cover .pic").attr("src") author = doc.selectFirst("ul.detail-list.cf > li:nth-of-type(2) > span:nth-of-type(2) > a").text() @@ -64,7 +71,9 @@ class ManHuaLou:HttpSource() { "连载中" -> SManga.ONGOING else -> SManga.UNKNOWN } - description = doc.select(".book-intro").last().text() + genre = doc.select("ul.detail-list.cf > li:nth-child(2) > span:nth-child(1) > a") + .map{ node -> node.text() }.joinToString(", ") + description = doc.selectFirst("#intro-all > p").text() } override fun chaptersRequest(page: Int, url: String): Request @@ -76,7 +85,7 @@ class ManHuaLou:HttpSource() { name = node.text() url = node.attr("href") } } - return PagedList(ret, false) + return PagedList(ret.reversed(), false) } override fun mangaPagesRequest(chapter: SChapter): Request @@ -92,5 +101,246 @@ class ManHuaLou:HttpSource() { return ret } + private open class UriPartFilter(displayName: String, val vals: Array>, + defaultValue: Int = 0) : + Filter.Select(displayName, vals.map { it.first }.toTypedArray(), defaultValue){ + open fun getUrl() = vals[state].second + } + private class Types :UriPartFilter("类型", arrayOf( + Pair("全部", ""), + Pair("儿童漫画", "ertong"), + Pair("少年漫画", "shaonian"), + Pair("少女漫画", "shaonv"), + Pair("青年漫画", "qingnian") + + )) + private class Orgins :UriPartFilter("地区", arrayOf( + Pair("全部", ""), + Pair("日本", "riben"), + Pair("大陆", "dalu"), + Pair("香港", "hongkong"), + Pair("台湾", "taiwan"), + Pair("欧美", "oumei"), + Pair("韩国", "hanguo"), + Pair("其他", "qita") + )) + private class Plots :UriPartFilter("剧情", arrayOf( + Pair("全部", ""), + Pair("爱情", "aiqing"), + Pair("少女爱情", "shaonvaiqing"), + Pair("欢乐向", "huanlexiang"), + Pair("耽美", "danmei"), + Pair("东方", "dongfang"), + Pair("其他", "qita"), + Pair("冒险", "maoxian"), + Pair("奇幻", "qihuan"), + Pair("性转换", "xingzhuanhuan"), + Pair("节操", "jiecao"), + Pair("舰娘", "jianniang"), + Pair("四格", "sige"), + Pair("科幻", "kehuan"), + Pair("校园", "xiaoyuan"), + Pair("竞技", "jingji"), + Pair("萌系", "mengxi"), + Pair("机战", "jizhan"), + Pair("后宫", "hougong"), + Pair("格斗", "gedou"), + Pair("百合", "baihe"), + Pair("魔幻", "mohuan"), + Pair("动作格斗", "dongzuogedou"), + Pair("魔法", "mofa"), + Pair("生活", "shenghuo"), + Pair("轻小说", "qingxiaoshuo"), + Pair("神鬼", "shengui"), + Pair("悬疑", "xuanyi"), + Pair("美食", "meishi"), + Pair("伪娘", "weiniang"), + Pair("治愈", "zhiyu"), + Pair("颜艺", "yanyi"), + Pair("恐怖", "kongbu"), + Pair("职场", "zhichang"), + Pair("热血", "rexue"), + Pair("侦探", "zhentan"), + Pair("搞笑", "gaoxiao"), + Pair("音乐舞蹈", "yinyuewudao"), + Pair("历史", "lishi"), + Pair("战争", "zhanzheng"), + Pair("励志", "lizhi"), + Pair("高清单行", "gaoqingdanxing"), + Pair("西方魔幻", "xifangmohuan"), + Pair("宅系", "zhaixi"), + Pair("魔幻神话", "mohuanshenhua"), + Pair("校园青春", "xiaoyuanqingchun"), + Pair("综合其它", "zongheqita"), + Pair("轻松搞笑", "qingsonggaoxiao"), + Pair("体育竞技", "tiyujingji"), + Pair("同人漫画", "tongrenmanhua"), + Pair("布卡漫画", "bukamanhua"), + Pair("科幻未来", "kehuanweilai"), + Pair("悬疑探案", "xuanyitanan"), + Pair("短篇漫画", "duanpianmanhua"), + Pair("萌", "meng"), + Pair("侦探推理", "zhentantuili"), + Pair("其它漫画", "qitamanhua"), + Pair("武侠格斗", "wuxiagedou"), + Pair("科幻魔幻", "kehuanmohuan"), + Pair("耽美BL", "danmeiBL"), + Pair("青春", "qingchun"), + Pair("恋爱", "lianai"), + Pair("神魔", "shenmo"), + Pair("恐怖鬼怪", "kongbuguiguai"), + Pair("青年漫画", "qingnianmanhua"), + Pair("四格漫画", "sigemanhua"), + Pair("搞笑喜剧", "gaoxiaoxiju"), + Pair("玄幻", "xuanhuan"), + Pair("动作", "dongzuo"), + Pair("武侠", "wuxia"), + Pair("穿越", "chuanyue"), + Pair("同人", "tongren"), + Pair("架空", "jiakong"), + Pair("霸总", "bazong"), + Pair("萝莉", "luoli"), + Pair("总裁", "zongcai"), + Pair("古风", "gufeng"), + Pair("推理", "tuili"), + Pair("恐怖灵异", "kongbulingyi"), + Pair("修真", "xiuzhen"), + Pair("灵异", "lingyi"), + Pair("真人", "zhenren"), + Pair("历史漫画", "lishimanhua"), + Pair("漫改", "mangai"), + Pair("剧情", "juqing"), + Pair("美少女", "meishaonv"), + Pair("故事", "gushi"), + Pair("都市", "dushi"), + Pair("社会", "shehui"), + Pair("竞技体育", "jingjitiyu"), + Pair("少女", "shaonv"), + Pair("御姐", "yujie"), + Pair("运动", "yundong"), + Pair("杂志", "zazhi"), + Pair("吸血", "xixie"), + Pair("泡泡", "paopao"), + Pair("彩虹", "caihong"), + Pair("恋爱生活", "lianaishenghuo"), + Pair("修真热血玄幻", "xiuzhenrexuexuanhuan"), + Pair("恋爱玄幻", "lianaixuanhuan"), + Pair("生活悬疑灵异", "shenghuoxuanyilingyi"), + Pair("霸总生活", "bazongshenghuo"), + Pair("恋爱生活玄幻", "lianaishenghuoxuanhuan"), + Pair("架空后宫古风", "jiakonghougonggufeng"), + Pair("生活悬疑古风", "shenghuoxuanyigufeng"), + Pair("恋爱热血玄幻", "lianairexuexuanhuan"), + Pair("恋爱校园生活", "lianaixiaoyuanshenghuo"), + Pair("玄幻动作", "xuanhuandongzuo"), + Pair("玄幻科幻", "xuanhuankehuan"), + Pair("恋爱生活励志", "lianaishenghuolizhi"), + Pair("悬疑恐怖", "xuanyikongbu"), + Pair("游戏", "youxi"), + Pair("恋爱生活科幻", "lianaishenghuokehuan"), + Pair("修真灵异动作", "xiuzhenlingyidongzuo"), + Pair("恋爱校园玄幻", "lianaixiaoyuanxuanhuan"), + Pair("热血动作", "rexuedongzuo"), + Pair("恋爱科幻", "lianaikehuan"), + Pair("恋爱搞笑玄幻", "lianaigaoxiaoxuanhuan"), + Pair("恋爱后宫古风", "lianaihougonggufeng"), + Pair("恋爱搞笑穿越", "lianaigaoxiaochuanyue"), + Pair("搞笑热血", "gaoxiaorexue"), + Pair("修真恋爱架空", "xiuzhenlianaijiakong"), + Pair("搞笑古风穿越", "gaoxiaogufengchuanyue"), + Pair("霸总恋爱生活", "bazonglianaishenghuo"), + Pair("恋爱古风穿越", "lianaigufengchuanyue"), + Pair("玄幻古风", "xuanhuangufeng"), + Pair("校园搞笑生活", "xiaoyuangaoxiaoshenghuo"), + Pair("恋爱校园", "lianaixiaoyuan"), + Pair("热血玄幻", "rexuexuanhuan"), + Pair("恋爱生活悬疑", "lianaishenghuoxuanyi"), + Pair("唯美", "weimei"), + Pair("霸总恋爱", "bazonglianai"), + Pair("悬疑动作", "xuanyidongzuo"), + Pair("搞笑生活", "gaoxiaoshenghuo"), + Pair("热血架空", "rexuejiakong"), + Pair("恋爱校园搞笑", "lianaixiaoyuangaoxiao"), + Pair("校园生活动作", "xiaoyuanshenghuodongzuo"), + Pair("恋爱搞笑生活", "lianaigaoxiaoshenghuo"), + Pair("修真热血动作", "xiuzhenrexuedongzuo"), + Pair("热血玄幻动作", "rexuexuanhuandongzuo"), + Pair("恋爱搞笑励志", "lianaigaoxiaolizhi"), + Pair("搞笑生活玄幻", "gaoxiaoshenghuoxuanhuan"), + Pair("恋爱搞笑科幻", "lianaigaoxiaokehuan"), + Pair("悬疑古风", "xuanyigufeng"), + Pair("恋爱架空古风", "lianaijiakonggufeng"), + Pair("热血科幻战争", "rexuekehuanzhanzheng"), + Pair("生活悬疑", "shenghuoxuanyi"), + Pair("修真玄幻", "xiuzhenxuanhuan"), + Pair("霸总恋爱玄幻", "bazonglianaixuanhuan"), + Pair("搞笑生活励志", "gaoxiaoshenghuolizhi"), + Pair("恋爱校园竞技", "lianaixiaoyuanjingji"), + Pair("冒险热血玄幻", "maoxianrexuexuanhuan"), + Pair("冒险热血", "maoxianrexue"), + Pair("恋爱冒险古风", "lianaimaoxiangufeng"), + Pair("恋爱搞笑古风", "lianaigaoxiaogufeng"), + Pair("恋爱古风", "lianaigufeng"), + Pair("霸总恋爱搞笑", "bazonglianaigaoxiao"), + Pair("恋爱玄幻古风", "lianaixuanhuangufeng"), + Pair("搞笑生活穿越", "gaoxiaoshenghuochuanyue"), + Pair("恋爱搞笑后宫", "lianaigaoxiaohougong"), + Pair("恋爱冒险玄幻", "lianaimaoxianxuanhuan"), + Pair("恋爱搞笑悬疑", "lianaigaoxiaoxuanyi"), + Pair("恋爱玄幻穿越", "lianaixuanhuanchuanyue"), + Pair("生活玄幻", "shenghuoxuanhuan"), + Pair("校园冒险搞笑", "xiaoyuanmaoxiangaoxiao"), + Pair("恋爱生活古风", "lianaishenghuogufeng"), + Pair("恋爱搞笑架空", "lianaigaoxiaojiakong"), + Pair("冒险热血动作", "maoxianrexuedongzuo"), + Pair("爆笑", "baoxiao"), + Pair("热血玄幻悬疑", "rexuexuanhuanxuanyi"), + Pair("恋爱冒险搞笑", "lianaimaoxiangaoxiao"), + Pair("修真生活玄幻", "xiuzhenshenghuoxuanhuan"), + Pair("恋爱悬疑", "lianaixuanyi"), + Pair("恋爱校园励志", "lianaixiaoyuanlizhi"), + Pair("修真恋爱古风", "xiuzhenlianaigufeng"), + Pair("复仇", "fuchou"), + Pair("虐心", "nuexin"), + Pair("纯爱", "chunai"), + Pair("蔷薇", "qiangwei"), + Pair("震撼", "zhenhan"), + Pair("惊悚", "jingsong") + )) + private class Letters :UriPartFilter("字母", arrayOf( + Pair("全部", ""), + Pair("A", "a"), + Pair("B", "b"), + Pair("C", "c"), + Pair("D", "d"), + Pair("E", "e"), + Pair("F", "f"), + Pair("G", "g"), + Pair("H", "h"), + Pair("I", "i"), + Pair("J", "j"), + Pair("K", "k"), + Pair("L", "l"), + Pair("M", "m"), + Pair("N", "n"), + Pair("O", "o"), + Pair("P", "p"), + Pair("Q", "q"), + Pair("R", "r"), + Pair("S", "s"), + Pair("T", "t"), + Pair("U", "u"), + Pair("V", "v"), + Pair("W", "w"), + Pair("X", "x"), + Pair("Y", "y"), + Pair("Z", "z"), + Pair("其他", "1") + )) + private class Progresses :UriPartFilter("进度", arrayOf( + Pair("全部", ""), + Pair("已完结", "wanjie"), + Pair("连载中", "lianzai") + )) } \ No newline at end of file From 76ff4d11d9b2ae8c889f68c88c900a16882f0d16 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 27 Jul 2019 11:33:47 +0800 Subject: [PATCH 05/27] Revert "Update gradle-wrapper.properties" This reverts commit baf92de4 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1a58ff9..16540b5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip From bd1c54d8fa1f50d8858220676b7232238c9a9be3 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 27 Jul 2019 11:35:28 +0800 Subject: [PATCH 06/27] fix source https://www.manhualou.com --- .../rechinx/meow/core/source/internal/ManHuaLou.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt index e58816e..415bee1 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt @@ -32,7 +32,7 @@ class ManHuaLou:HttpSource() { } else{ val params = filters.map { (it as UriPartFilter).getUrl() }.joinToString("-") if("" != params){ - return GET("$baseUrl/list/${params}_$page/") + return GET("$baseUrl/list/$params/$page/") } return GET("$baseUrl/list_$page/") } @@ -43,12 +43,13 @@ class ManHuaLou:HttpSource() { private fun commonMangaParse(response: Response): PagedList { val res = response.body()!!.string() - val ret = Jsoup.parse(res).select("#contList li").map { node -> SManga.create().apply { + val doc = Jsoup.parse(res) + val ret = doc.select("#contList li").map { node -> SManga.create().apply { title = node.selectFirst("p").text() thumbnail_url = node.selectFirst("img").attr("src") url = node.selectFirst("a").attr("href") } } - return PagedList(ret, true) + return PagedList(ret, doc.select(".next") != null && doc.select(".next.disabled") == null) } override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/list_$page/") @@ -66,14 +67,14 @@ class ManHuaLou:HttpSource() { title = doc.selectFirst(".book-title").text() thumbnail_url = doc.selectFirst(".cover .pic").attr("src") author = doc.selectFirst("ul.detail-list.cf > li:nth-of-type(2) > span:nth-of-type(2) > a").text() - status = when(doc.selectFirst(".status a").text()) { + status = when(doc.selectFirst("li.status a").text()) { "已完结" -> SManga.COMPLETED "连载中" -> SManga.ONGOING else -> SManga.UNKNOWN } genre = doc.select("ul.detail-list.cf > li:nth-child(2) > span:nth-child(1) > a") .map{ node -> node.text() }.joinToString(", ") - description = doc.selectFirst("#intro-all > p").text() + description = doc.selectFirst("#intro-all > p").text()+ "\n\n" + doc.selectFirst("li.status").text() } override fun chaptersRequest(page: Int, url: String): Request From ddbfb4c8bce244ac1c7ea381d75febec653a05a4 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 27 Jul 2019 11:49:04 +0800 Subject: [PATCH 07/27] add source https://www.manhualou.com --- .../java/top/rechinx/meow/core/source/internal/ManHuaLou.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt index 415bee1..ad1cf54 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt @@ -49,7 +49,7 @@ class ManHuaLou:HttpSource() { thumbnail_url = node.selectFirst("img").attr("src") url = node.selectFirst("a").attr("href") } } - return PagedList(ret, doc.select(".next") != null && doc.select(".next.disabled") == null) + return PagedList(ret, doc.selectFirst(".next") != null && doc.selectFirst(".next.disabled") == null) } override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/list_$page/") From 4e6fc9309df715aa35fc6f7becd1e4e9263b26cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E7=BA=A2=E6=9F=BF=E5=A4=A7=E8=8A=9D=E9=BA=BB?= <747455334@qq.com> Date: Sat, 27 Jul 2019 13:47:45 +0800 Subject: [PATCH 08/27] Update gradle-wrapper.properties --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 16540b5..418447c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip From 60807bf22389dd9669109796da61e8deba248b51 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 27 Jul 2019 19:48:46 +0800 Subject: [PATCH 09/27] add source https://www.tohomh123.com --- .../rechinx/meow/core/source/SourceManager.kt | 4 +- .../meow/core/source/internal/ManHuaLou.kt | 11 ++- .../meow/core/source/internal/Tohomh.kt | 95 +++++++++++++++++++ 3 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/Tohomh.kt diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index 5fefa11..16abc57 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -3,6 +3,7 @@ package top.rechinx.meow.core.source import android.content.Context import top.rechinx.meow.core.source.internal.Dmzj import top.rechinx.meow.core.source.internal.ManHuaLou +import top.rechinx.meowo.core.source.internal.Tohomh class SourceManager(private val context: Context) { @@ -38,7 +39,8 @@ class SourceManager(private val context: Context) { private fun createInternalSources(): List = listOf( Dmzj(), - ManHuaLou() + ManHuaLou(), + Tohomh() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt index ad1cf54..f9d5602 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt @@ -8,6 +8,8 @@ import org.jsoup.Jsoup import top.rechinx.meow.core.source.HttpSource import top.rechinx.meow.core.source.model.* +import java.text.SimpleDateFormat +import java.util.Locale class ManHuaLou:HttpSource() { @@ -74,18 +76,21 @@ class ManHuaLou:HttpSource() { } genre = doc.select("ul.detail-list.cf > li:nth-child(2) > span:nth-child(1) > a") .map{ node -> node.text() }.joinToString(", ") - description = doc.selectFirst("#intro-all > p").text()+ "\n\n" + doc.selectFirst("li.status").text() + description = doc.selectFirst("#intro-all > p").text() } override fun chaptersRequest(page: Int, url: String): Request = GET(url) override fun chaptersParse(response: Response): PagedList { - val res = response.body()!!.string() - val ret = Jsoup.parse(res).select(".chapter-body.clearfix a").map { node -> SChapter.create().apply { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".chapter-body.clearfix a").map { node -> SChapter.create().apply { name = node.text() url = node.attr("href") } } + doc.selectFirst("li.status .red").text().let { + ret[0].date_updated = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA).parse(it).time + } return PagedList(ret.reversed(), false) } diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Tohomh.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Tohomh.kt new file mode 100644 index 0000000..3bccf9b --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Tohomh.kt @@ -0,0 +1,95 @@ +package top.rechinx.meowo.core.source.internal + +import okhttp3.Request +import okhttp3.Response +import org.json.JSONObject +import org.jsoup.Jsoup +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* +import java.text.SimpleDateFormat +import java.util.* +import kotlin.collections.ArrayList + +class Tohomh:HttpSource() { + + override val name = "Tohomh123" + + override val baseUrl = "https://www.tohomh123.com" + + private fun GET(url: String) = Request.Builder() + .url(url) + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request + = GET("$baseUrl/action/Search?keyword=$keyword&page=$page") + + override fun searchMangaParse(response: Response): PagedList = commonMangaParse(response) + + private fun commonMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select("div.mh-item").map { node -> SManga.create().apply { + title = node.selectFirst("h2 a").text() + thumbnail_url = node.selectFirst("p.mh-cover").attr("style").substringAfter("(").substringBefore(")") + url = baseUrl + node.selectFirst("h2 a").attr("href") + } } + return PagedList(ret, doc.selectFirst("div.page-pagination a:contains(>)") != null) + } + + override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/f-1-------hits--$page.html") + + override fun popularMangaParse(response: Response): PagedList = commonMangaParse(response) + + override fun mangaInfoRequest(url: String): Request = GET(url) + + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { + val infoElement = Jsoup.parse(response.body()!!.string()).selectFirst(".banner_detail_form") + title = infoElement.selectFirst("h1").text() + thumbnail_url = infoElement.selectFirst(".cover img").attr("src") + author = infoElement.selectFirst(".subtitle").text().substringAfter(":").trim() + status = when(infoElement.selectFirst("span:nth-of-type(1) span").text()) { + "连载中" -> SManga.ONGOING + "完结" -> SManga.COMPLETED + else -> SManga.UNKNOWN + } + genre = infoElement.select(".tip a") + .map{ node -> node.text() }.joinToString(", ") + description = infoElement.select("p.content").text() + } + + override fun chaptersRequest(page: Int, url: String): Request = GET(url) + + override fun chaptersParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select("ul#detail-list-select-1 a").map { node -> SChapter.create().apply { + name = node.text() + url = node.attr("href") + } } + doc.select(".banner_detail_form span:nth-of-type(3)").text() + .substringAfter(":").trim().let { + ret[0].date_updated = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA).parse(it).time + } + return PagedList(ret, false) + } + + override fun mangaPagesRequest(chapter: SChapter): Request = GET(baseUrl + chapter.url) + + override fun mangaPagesParse(response: Response): List { + val doc = Jsoup.parse(response.body()!!.string()) + val script = doc.select("script:containsData(did)").first().data() + val did = script.substringAfter("did=").substringBefore(";") + val sid = script.substringAfter("sid=").substringBefore(";") + val lastPage = script.substringAfter("pcount =").substringBefore(";").trim().toInt() + val ret = ArrayList(lastPage) + for (i in 1..lastPage) { + ret.add(MangaPage(i, "$baseUrl/action/play/read?did=$did&sid=$sid&iid=$i", "")) + } + return ret + } + + override fun imageUrlParse(response: Response): String + = JSONObject(response.body()!!.string()).getString("Code") + + override fun getFilterList(): FilterList = FilterList() + +} \ No newline at end of file From d1f0132b74ce15b2bc94110cae4ccd6f352f8997 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Tue, 6 Aug 2019 11:02:49 +0800 Subject: [PATCH 10/27] add source https://manga.bilibili.com --- .../java/top/rechinx/meow/core/source/internal/Bilibili.kt | 4 ++++ .../main/java/top/rechinx/meow/core/source/internal/Tohomh.kt | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt new file mode 100644 index 0000000..55df371 --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt @@ -0,0 +1,4 @@ +package top.rechinx.meow.core.source.internal + +class Bilibili { +} \ No newline at end of file diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Tohomh.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Tohomh.kt index 3bccf9b..ec4a624 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/Tohomh.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Tohomh.kt @@ -7,8 +7,7 @@ import org.jsoup.Jsoup import top.rechinx.meow.core.source.HttpSource import top.rechinx.meow.core.source.model.* import java.text.SimpleDateFormat -import java.util.* -import kotlin.collections.ArrayList +import java.util.Locale class Tohomh:HttpSource() { From 13b2ee2cda303021dd1df58b5a2228b275792632 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Tue, 6 Aug 2019 16:17:47 +0800 Subject: [PATCH 11/27] add source https://manga.bilibili.com --- .../rechinx/meow/core/source/SourceManager.kt | 4 +- .../meow/core/source/internal/Bilibili.kt | 241 +++++++++++++++++- .../rechinx/meow/core/source/internal/Dmzj.kt | 2 +- .../meow/core/source/internal/ManHuaLou.kt | 3 +- 4 files changed, 245 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index 16abc57..41f4f2e 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -1,6 +1,7 @@ package top.rechinx.meow.core.source import android.content.Context +import top.rechinx.meow.core.source.internal.Bilibili import top.rechinx.meow.core.source.internal.Dmzj import top.rechinx.meow.core.source.internal.ManHuaLou import top.rechinx.meowo.core.source.internal.Tohomh @@ -40,7 +41,8 @@ class SourceManager(private val context: Context) { private fun createInternalSources(): List = listOf( Dmzj(), ManHuaLou(), - Tohomh() + Tohomh(), + Bilibili() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt index 55df371..83ccb09 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt @@ -1,4 +1,243 @@ package top.rechinx.meow.core.source.internal -class Bilibili { +import okhttp3.* +import org.json.JSONObject +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* +import java.util.zip.ZipInputStream +import kotlin.experimental.xor + +class Bilibili:HttpSource() { + + override val name = "Bilibili" + override val baseUrl = "https://manga.bilibili.com" + private val cleanRegex = Regex("") + + private fun POST(url: String, json:String) = Request.Builder() + .url(url) + .post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json)) + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request { + if("" != keyword){ + return POST("$baseUrl/twirp/comic.v1.Comic/Search?device=pc&platform=web", + "{\"key_word\":\"$keyword\",\"page_num\":$page,\"page_size\":9}") + } else{ + val json = filters.map { (it as UriPartFilter).getUrl() }.joinToString(",") + return POST("$baseUrl/twirp/comic.v1.Comic/ClassPage?device=pc&platform=web", + "{$json,\"page_num\":$page,\"page_size\":18}") + } + } + + private fun commonMangaParse(response: Response): PagedList { + val json = JSONObject(response.body()!!.string()) + if(response.request().url().toString().contains("Search")){ + val data = json.getJSONObject("data") + val arr = data.getJSONArray("list") + val ret = ArrayList() + for (i in 0 until arr.length()) { + val info = arr.getJSONObject(i) + ret.add(SManga.create().apply { + title = info.getString("title").replace(cleanRegex, "") + thumbnail_url = info.getString("vertical_cover") + url = info.getInt("id").toString() + + val tmp = ArrayList() + val styles = info.getJSONArray("styles") + for (j in 0 until styles.length()) { + tmp.add(styles.getString(j)) + } + genre = tmp.joinToString(", ") + + tmp.clear() + val authors = info.getJSONArray("author_name") + for (j in 0 until authors.length()) { + tmp.add(authors.getString(j)) + } + author = tmp.joinToString(", ").replace(cleanRegex, "") + }) + } + return PagedList(ret, true) + } + else{ + val arr = json.getJSONArray("data") + val ret = ArrayList(arr.length()) + for (i in 0 until arr.length()) { + val info = arr.getJSONObject(i) + ret.add(SManga.create().apply { + title = info.getString("title") + thumbnail_url = info.getString("vertical_cover") + url = info.getInt("season_id").toString() + }) + } + return PagedList(ret, true) + } + } + + override fun searchMangaParse(response: Response): PagedList = commonMangaParse(response) + + override fun popularMangaRequest(page: Int): Request = POST("$baseUrl/twirp/comic.v1.Comic/ClassPage?device=pc&platform=web", + "{\"style_id\":-1,\"area_id\":-1,\"is_finish\":-1,\"order\":0,\"page_num\":$page,\"page_size\":18,\"is_free\":-1}") + + override fun popularMangaParse(response: Response): PagedList = commonMangaParse(response) + + override fun mangaInfoRequest(url: String): Request = POST("$baseUrl/twirp/comic.v2.Comic/ComicDetail?device=pc&platform=web","{\"comic_id\":$url}") + + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { + val json = JSONObject(response.body()!!.string()) + val data = json.getJSONObject("data") + title = data.getString("title") + thumbnail_url = data.getString("vertical_cover") + url = data.getInt("id").toString() + val tmp = ArrayList() + val authors = data.getJSONArray("author_name") + for (j in 0 until authors.length()) { + tmp.add(authors.getString(j)) + } + author = tmp.joinToString(", ") + + status = when(data.getInt("is_finish")) { + 1 -> SManga.COMPLETED + 0 -> SManga.ONGOING + else -> SManga.UNKNOWN + } + + tmp.clear() + val styles = data.getJSONArray("styles") + for (j in 0 until styles.length()) { + tmp.add(styles.getString(j)) + } + genre = tmp.joinToString(", ") + + description = data.getString("evaluate") + } + + override fun chaptersRequest(page: Int, url: String): Request = POST("$baseUrl/twirp/comic.v2.Comic/ComicDetail?device=pc&platform=web","{\"comic_id\":$url}") + + override fun chaptersParse(response: Response): PagedList { + val json = JSONObject(response.body()!!.string()) + val data = json.getJSONObject("data") + val list = data.getJSONArray("ep_list") + + val ret = ArrayList() + for (i in 0 until list.length()) { + val chapter = list.getJSONObject(i) + ret.add(SChapter.create().apply { + name = (when(chapter.getBoolean("is_locked")){ + true -> "🔒" + chapter.getString("short_title") + false -> chapter.getString("short_title") + }) + url = chapter.getInt("id").toString() + }) + } + return PagedList(ret, false) + } + + override fun mangaPagesRequest(chapter: SChapter): Request = POST("$baseUrl/twirp/comic.v1.Comic/GetImageIndex?device=pc&platform=web","{\"ep_id\":${chapter.url}}") + + + override fun mangaPagesParse(response: Response): List { + val json = JSONObject(response.body()!!.string()) + if("" != json.getString("msg")){ + val ret = ArrayList() + ret.add(MangaPage(0, "", "https://i0.hdslb.com/bfs/activity-plat/cover/20171017/496nrnmz9x.png")) + return ret + } + + val data = json.getJSONObject("data") + val path = data.getString("path") + val m = Regex("^/bfs/manga/(\\d+)/(\\d+)").find(path)!! + val cid = m.groupValues[1].toInt() + val epid = m.groupValues[2].toInt() + + var bytes = client.newCall(Request.Builder() + .url("https://i0.hdslb.com$path") + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build()).execute().body()!!.bytes() + bytes = bytes.sliceArray(9 until bytes.size) + + val key = ByteArray(8) + key[0] = epid.toByte() + key[1] = epid.shr(8).toByte() + key[2] = epid.shr(16).toByte() + key[3] = epid.shr(24).toByte() + key[4] = cid.toByte() + key[5] = cid.shr(8).toByte() + key[6] = cid.shr(16).toByte() + key[7] = cid.shr(24).toByte() + for (i in 0 until bytes.size){ + bytes[i] = bytes[i].xor(key[i % 8]) + } + + val zis = ZipInputStream(bytes.inputStream()) + zis.nextEntry + val pics = JSONObject(zis.bufferedReader().use { it.readText() }).getJSONArray("pics") + val tokens = JSONObject(client.newCall(POST("$baseUrl/twirp/comic.v1.Comic/ImageToken?device=pc&platform=web", + "{\"urls\":\"${pics.toString().replace("\"","\\\"")}\"}")) + .execute().body()!!.string()).getJSONArray("data") + val ret = ArrayList() + for (i in 0 until tokens.length()) { + val token = tokens.getJSONObject(i) + ret.add(MangaPage(i, "", "${token.getString("url")}?token=${token.getString("token")}")) + } + return ret + } + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") + + override fun getFilterList(): FilterList = FilterList(StylesFilter(), AreasFilter(), StatusFilter(), PricesFilter(), OrdersFilter()) + + private open class UriPartFilter(displayName: String, val vals: Array>, + defaultValue: Int = 0) : + Filter.Select(displayName, vals.map { it.first }.toTypedArray(), defaultValue){ + open fun getUrl() = vals[state].second + } + + private class StylesFilter : UriPartFilter("题材", arrayOf( + Pair("全部", "\"style_id\":-1"), + Pair("冒险", "\"style_id\":1013"), + Pair("热血", "\"style_id\":999"), + Pair("搞笑", "\"style_id\":994"), + Pair("恋爱", "\"style_id\":995"), + Pair("少女", "\"style_id\":1026"), + Pair("日常", "\"style_id\":1020"), + Pair("校园", "\"style_id\":1001"), + Pair("运动", "\"style_id\":1010"), + Pair("正能量", "\"style_id\":1028"), + Pair("治愈", "\"style_id\":1007"), + Pair("古风", "\"style_id\":997"), + Pair("玄幻", "\"style_id\":1016"), + Pair("奇幻", "\"style_id\":998"), + Pair("惊奇", "\"style_id\":996"), + Pair("悬疑", "\"style_id\":1023"), + Pair("都市", "\"style_id\":1002"), + Pair("总裁", "\"style_id\":1004") + )) + + private class AreasFilter : UriPartFilter("地区", arrayOf( + Pair("全部", "\"area_id\":-1"), + Pair("大陆", "\"area_id\":1"), + Pair("日本", "\"area_id\":2"), + Pair("其他", "\"area_id\":5") + )) + + private class StatusFilter : UriPartFilter("进度", arrayOf( + Pair("全部", "\"is_finish\":-1"), + Pair("连载", "\"is_finish\":0"), + Pair("完结", "\"is_finish\":1"), + Pair("新上架", "\"is_finish\":2") + )) + + private class PricesFilter : UriPartFilter("收费", arrayOf( + Pair("全部", "\"is_free\":-1"), + Pair("免费", "\"is_free\":1"), + Pair("付费", "\"is_free\":2") + )) + + private class OrdersFilter : UriPartFilter("排序", arrayOf( + Pair("人气推荐", "\"order\":0"), + Pair("更新时间", "\"order\":1"), + Pair("追漫人数", "\"order\":2") + )) } \ No newline at end of file diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Dmzj.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Dmzj.kt index 0d626ce..805497f 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/Dmzj.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Dmzj.kt @@ -16,7 +16,7 @@ class Dmzj: HttpSource() { private fun GET(url: String) = Request.Builder() .url(url) - .addHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 ") + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") .build() override fun searchMangaRequest(query: String, page: Int, filterList: FilterList): Request { diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt index f9d5602..201e95d 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaLou.kt @@ -62,8 +62,7 @@ class ManHuaLou:HttpSource() { override fun mangaInfoRequest(url: String): Request = GET(url) - override fun mangaInfoParse(response: Response): SManga - = SManga.create().apply { + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { val res = response.body()!!.string() val doc = Jsoup.parse(res) title = doc.selectFirst(".book-title").text() From 049e1dca2391c47363da7b8bcbc3fdb4cff58c8f Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Tue, 6 Aug 2019 18:41:03 +0800 Subject: [PATCH 12/27] add source http://www.u17.com --- .../rechinx/meow/core/source/SourceManager.kt | 4 +- .../rechinx/meow/core/source/internal/U17.kt | 95 +++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index 41f4f2e..92f93ea 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -4,6 +4,7 @@ import android.content.Context import top.rechinx.meow.core.source.internal.Bilibili import top.rechinx.meow.core.source.internal.Dmzj import top.rechinx.meow.core.source.internal.ManHuaLou +import top.rechinx.meow.core.source.internal.U17 import top.rechinx.meowo.core.source.internal.Tohomh class SourceManager(private val context: Context) { @@ -42,7 +43,8 @@ class SourceManager(private val context: Context) { Dmzj(), ManHuaLou(), Tohomh(), - Bilibili() + Bilibili(), + U17() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt new file mode 100644 index 0000000..d0c3210 --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt @@ -0,0 +1,95 @@ +package top.rechinx.meow.core.source.internal + +import android.util.Base64 +import okhttp3.Request +import okhttp3.Response +import org.json.JSONObject +import org.jsoup.Jsoup +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* + +class U17:HttpSource() { + + override val name = "U17" + override val baseUrl = "http://www.u17.com" + + private fun GET(url: String) = Request.Builder() + .url(url) + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request = GET("http://so.u17.com/all/$keyword/m0_p$page.html") + + override fun searchMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".comiclist li").map { node -> SManga.create().apply { + title = node.selectFirst("h3 a").text() + thumbnail_url = node.selectFirst("img").attr("src") + url = node.selectFirst("a").attr("href") + author = node.select("h3>a")?.text() + } } + return PagedList(ret, doc.selectFirst(".next") != null && doc.selectFirst(".next.over") == null) + } + + override fun popularMangaRequest(page: Int): Request = GET(baseUrl) + + override fun popularMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".comic_all li").map { node -> SManga.create().apply { + title = node.selectFirst("a[title]").attr("title") + thumbnail_url = node.selectFirst("img").attr("xsrc") + url = node.selectFirst("a").attr("href") + } } + return PagedList(ret, doc.selectFirst(".next") != null && doc.selectFirst(".next.over") == null) + } + + override fun mangaInfoRequest(url: String): Request = GET(url) + + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { + Jsoup.parse(response.body()!!.string()).selectFirst(".comic_info").let { + title = it.selectFirst("h1").text() + thumbnail_url = it.selectFirst(".cover img").attr("src") + author = it.selectFirst(".author_info .info a").text() + status = when(it.selectFirst(".comic_infor_status span").text()) { + "已完结" -> SManga.COMPLETED + "连载中" -> SManga.ONGOING + else -> SManga.UNKNOWN + } + genre = it.select(".class_tag") + .map{ node -> node.text() }.joinToString(", ") + description = it.selectFirst(".words").text() + } + } + + override fun chaptersRequest(page: Int, url: String): Request = GET(url) + + override fun chaptersParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select("#chapter li").map { node -> SChapter.create().apply { + name = when(node.selectFirst("a").attr("class")){ + "vip_chapter" -> "🔒" + node.text() + else -> node.text() + } + url = node.selectFirst("a").attr("href") + } } + return PagedList(ret.reversed(), false) + } + + override fun mangaPagesRequest(chapter: SChapter): Request = GET(chapter.url!!) + + override fun mangaPagesParse(response: Response): List { + val res = response.body()!!.string() + val list = JSONObject(Regex("image_list\\s*:\\s*(.*?\\}\\})").find(res)!!.groupValues[1]) + val ret = ArrayList() + var i = 0 + list.keys().forEach { + ret.add(MangaPage(i, "", String(Base64.decode(list.getJSONObject(it).getString("src"), Base64.NO_WRAP)))) + i++ + } + return ret + } + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") + + override fun getFilterList(): FilterList = FilterList() +} \ No newline at end of file From 4ee5f029cf919923726cdcc9598d84b39ac76c34 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Tue, 6 Aug 2019 19:00:50 +0800 Subject: [PATCH 13/27] add source http://www.u17.com --- app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt index d0c3210..3b9757e 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt @@ -66,7 +66,7 @@ class U17:HttpSource() { override fun chaptersParse(response: Response): PagedList { val doc = Jsoup.parse(response.body()!!.string()) val ret = doc.select("#chapter li").map { node -> SChapter.create().apply { - name = when(node.selectFirst("a").attr("class")){ + name = when(node.selectFirst("a").className()){ "vip_chapter" -> "🔒" + node.text() else -> node.text() } From 5cc4c9b327b551920e0f3cfa7aa8a11b908cbd55 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Wed, 7 Aug 2019 23:04:58 +0800 Subject: [PATCH 14/27] fix --- .../java/top/rechinx/meow/core/source/internal/Bilibili.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt index 83ccb09..745d5fd 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Bilibili.kt @@ -90,6 +90,7 @@ class Bilibili:HttpSource() { title = data.getString("title") thumbnail_url = data.getString("vertical_cover") url = data.getInt("id").toString() + val tmp = ArrayList() val authors = data.getJSONArray("author_name") for (j in 0 until authors.length()) { @@ -147,12 +148,16 @@ class Bilibili:HttpSource() { val data = json.getJSONObject("data") val path = data.getString("path") + var host = "https://i0.hdslb.com" + if(data.has("host") && ""!=data.getString("host")){ + host = data.getString("host") + } val m = Regex("^/bfs/manga/(\\d+)/(\\d+)").find(path)!! val cid = m.groupValues[1].toInt() val epid = m.groupValues[2].toInt() var bytes = client.newCall(Request.Builder() - .url("https://i0.hdslb.com$path") + .url(host+path) .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") .build()).execute().body()!!.bytes() bytes = bytes.sliceArray(9 until bytes.size) From 01f10a21b002e1439d57fb3a1a521878693a2f73 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Fri, 9 Aug 2019 00:39:21 +0800 Subject: [PATCH 15/27] add source https://ac.qq.com/ --- .../rechinx/meow/core/source/SourceManager.kt | 8 +- .../meow/core/source/internal/Tencent.kt | 94 +++++++++++++++++++ 2 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/Tencent.kt diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index 92f93ea..5d8743c 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -1,10 +1,7 @@ package top.rechinx.meow.core.source import android.content.Context -import top.rechinx.meow.core.source.internal.Bilibili -import top.rechinx.meow.core.source.internal.Dmzj -import top.rechinx.meow.core.source.internal.ManHuaLou -import top.rechinx.meow.core.source.internal.U17 +import top.rechinx.meow.core.source.internal.* import top.rechinx.meowo.core.source.internal.Tohomh class SourceManager(private val context: Context) { @@ -44,7 +41,8 @@ class SourceManager(private val context: Context) { ManHuaLou(), Tohomh(), Bilibili(), - U17() + U17(), + Tencent() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Tencent.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Tencent.kt new file mode 100644 index 0000000..4aa5d8f --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Tencent.kt @@ -0,0 +1,94 @@ +package top.rechinx.meow.core.source.internal + +import android.util.Base64 +import okhttp3.Request +import okhttp3.Response +import org.json.JSONArray +import org.jsoup.Jsoup +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* + +class Tencent:HttpSource() { + override val name = "Tencent" + override val baseUrl = "https://ac.qq.com" + + private fun GET(url: String) = Request.Builder() + .url(url) + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request = GET("$baseUrl/Comic/searchList?search=$keyword&page=$page") + + override fun searchMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".mod_book_list li").map { node -> SManga.create().apply { + title = node.selectFirst("h4").text() + thumbnail_url = node.selectFirst("img").attr("data-original") + url = baseUrl + node.selectFirst("a").attr("href") + } } + return PagedList(ret, true/*doc.selectFirst(".mod_page_next") != null*/) + } + + override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/Comic/all/search/time/page/$page") + + override fun popularMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".ret-search-list li").map { node -> SManga.create().apply { + title = node.selectFirst("h3").text() + thumbnail_url = node.selectFirst("img").attr("data-original") + url = baseUrl+ node.selectFirst("a").attr("href") + author = node.selectFirst(".ret-works-author").text() + } } + return PagedList(ret, true/*doc.selectFirst(".mod_page_next") != null*/) + } + + override fun mangaInfoRequest(url: String): Request = GET(url) + + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { + Jsoup.parse(response.body()!!.string()).selectFirst(".works-intro-wr").let { + title = it.selectFirst("h2").text() + thumbnail_url = it.selectFirst(".works-cover img").attr("src") + author = it.selectFirst(".works-intro-digi em").text() +// status = when(it.selectFirst(".comic_infor_status span").text()) { +//// "已完结" -> SManga.COMPLETED +//// "连载中" -> SManga.ONGOING +//// else -> SManga.UNKNOWN +//// } + genre = it.select(".works-intro-tags a") + .map{ node -> node.text() }.joinToString(", ") + description = it.selectFirst(".works-intro-short").text() + } + } + + override fun chaptersRequest(page: Int, url: String): Request = GET(url) + + override fun chaptersParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".chapter-page-all span").map { node -> SChapter.create().apply { + name = when(node.selectFirst("i").className()){ + "ui-icon-pay" -> "🔒" + node.text() + else -> node.text() + } + url = node.selectFirst("a").attr("href") + } } + return PagedList(ret.reversed(), false) + } + + override fun mangaPagesRequest(chapter: SChapter): Request = GET(baseUrl + chapter.url!!) + + override fun mangaPagesParse(response: Response): List { + val res = response.body()!!.string() + val DATA = res.substringAfter("DATA = '").substringBefore("'") + val pic = String(Base64.decode(DATA.substring(DATA.length%4), Base64.NO_WRAP)) + val arr = JSONArray(pic.substringAfter("\"picture\":").substringBefore("]")+"]") + val ret = ArrayList() + for (i in 0 until arr.length()) { + ret.add(MangaPage(i, "", arr.getJSONObject(i).getString("url"))) + } + return ret + } + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") + + override fun getFilterList(): FilterList = FilterList() +} \ No newline at end of file From 0bbc16ed76fcf6ebb96a87108f818c7e5373ef95 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Fri, 9 Aug 2019 10:52:39 +0800 Subject: [PATCH 16/27] =?UTF-8?q?add=20source=20=E5=A7=91=E4=B8=94?= =?UTF-8?q?=E5=8F=AB=E5=81=9A=E6=BC=AB=E7=94=BB=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rechinx/meow/core/source/SourceManager.kt | 3 +- .../meow/core/source/internal/Manhuatai.kt | 114 ++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/Manhuatai.kt diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index 5d8743c..8b2bc88 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -42,7 +42,8 @@ class SourceManager(private val context: Context) { Tohomh(), Bilibili(), U17(), - Tencent() + Tencent(), + Manhuatai() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Manhuatai.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Manhuatai.kt new file mode 100644 index 0000000..cb43a13 --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Manhuatai.kt @@ -0,0 +1,114 @@ +package top.rechinx.meow.core.source.internal + +import okhttp3.Request +import okhttp3.Response +import org.json.JSONObject +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* + +class Manhuatai:HttpSource() { + override val name = "漫画台" + override val baseUrl = "http://getcomicinfo-globalapi.yyhao.com" + + private fun GET(url: String) = Request.Builder() + .url(url) + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request + = GET("$baseUrl/app_api/v5/getsortlist/?search_key=$keyword&page=$page") + + private fun commonMangaParse(response: Response): PagedList{ + val json = JSONObject(response.body()!!.string()) + val data = json.getJSONArray("data") + val ret = ArrayList() + for(i in 0 until data.length()){ + ret.add(SManga.create().apply { + val manga = data.getJSONObject(i) + val id = manga.getInt("comic_id").toString() + title = manga.getString("comic_name") + thumbnail_url = "http://image.mhxk.com/mh/$id.jpg" + genre = manga.getString("comic_type") + url = "$baseUrl/app_api/v5/getcomicinfo_body/?comic_id=$id" + }) + } + return PagedList(ret, true) + } + + override fun searchMangaParse(response: Response): PagedList = commonMangaParse(response) + + override fun popularMangaRequest(page: Int): Request + = GET("$baseUrl/app_api/v5/getsortlist/?page=$page") + + override fun popularMangaParse(response: Response): PagedList = commonMangaParse(response) + + override fun mangaInfoRequest(url: String): Request = GET(url) + + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { + JSONObject(response.body()!!.string()).let { + title = it.getString("comic_name") + thumbnail_url = it.getJSONArray("cover_list").getString(0) + author = it.getString("comic_author") + status = when(it.getInt("comic_status")) { + 0 -> SManga.COMPLETED + 1 -> SManga.ONGOING + else -> SManga.UNKNOWN + } + + val types = it.getJSONObject("comic_type") + val tmp = ArrayList() + for (key in types.keys()) { + tmp.add(types.getString(key)) + } + genre = tmp.joinToString(", ") + + description = it.getString("comic_desc") + } + } + + override fun chaptersRequest(page: Int, url: String): Request = GET(url) + + override fun chaptersParse(response: Response): PagedList { + val json = JSONObject(response.body()!!.string()) + val chapters = json.getJSONArray("comic_chapter") + val ret = ArrayList() + for(i in 0 until chapters.length()){ + val chapter = chapters.getJSONObject(i) + ret.add(SChapter.create().apply { + name = when(chapter.getInt("islock")) { + 1 -> "🔒" + chapter.getString("chapter_name") + else -> chapter.getString("chapter_name") + } + url = response.request().url().toString()+"&chapter="+i.toString() + chapter_number = i.toString() + date_updated = 1000 * chapter.getLong("create_date") + }) + } + return PagedList(ret, false) + } + + override fun mangaPagesRequest(chapter: SChapter): Request = GET(chapter.url!!) + + override fun mangaPagesParse(response: Response): List { + JSONObject(response.body()!!.string()) + .getJSONArray("comic_chapter") + .getJSONObject(response.request().url().queryParameter("chapter")!!.toInt()) + .let{ + val rule = it.getJSONObject("chapter_image").getString("high") + val ext = rule.split("$$")[1] + val server = "https://mhpic."+it.getString("chapter_domain")+rule.split("$$")[0] + val ret = ArrayList() + for(i in 1 .. it.getInt("end_num")){ + ret.add(MangaPage(i, "", server+i.toString()+ext)) + } + return ret + } + } + + override fun headersBuilder() + = super.headersBuilder().add("Referer", baseUrl)!! + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") + + override fun getFilterList(): FilterList = FilterList() +} \ No newline at end of file From 75ccc3edd97cc4fe88154ca2506918cc2490c54a Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Fri, 9 Aug 2019 18:50:24 +0800 Subject: [PATCH 17/27] add source https://www.dongmanmanhua.cn --- .../rechinx/meow/core/source/SourceManager.kt | 3 +- .../meow/core/source/internal/DongMan.kt | 83 +++++++++++++++++++ .../internal/{Manhuatai.kt => ManHuaTai.kt} | 17 ++-- .../meow/core/source/internal/Tencent.kt | 8 +- 4 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/DongMan.kt rename app/src/main/java/top/rechinx/meow/core/source/internal/{Manhuatai.kt => ManHuaTai.kt} (92%) diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index 8b2bc88..bb6dda3 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -43,7 +43,8 @@ class SourceManager(private val context: Context) { Bilibili(), U17(), Tencent(), - Manhuatai() + ManHuaTai(), + DongMan() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/DongMan.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/DongMan.kt new file mode 100644 index 0000000..e831d01 --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/DongMan.kt @@ -0,0 +1,83 @@ +package top.rechinx.meow.core.source.internal + +import okhttp3.Request +import okhttp3.Response +import org.jsoup.Jsoup +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* +import java.net.URI +import java.util.ArrayList + +class DongMan:HttpSource() { + override val name = "咚漫" + override val baseUrl = "https://www.dongmanmanhua.cn" + + private fun GET(url: String) = Request.Builder() + .url(URI(baseUrl).resolve(url).toString()) + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request + = GET("$baseUrl/search?keyword=$keyword&page=$page") + private fun commonMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".card_lst li").map { node -> SManga.create().apply { + title = node.selectFirst(".subj").text() + thumbnail_url = node.selectFirst("img").attr("src") + url = node.selectFirst("a").attr("href") + author = node.selectFirst(".author").text() + genre = node.selectFirst(".genre").text() + } } + return PagedList(ret, true) + } + override fun searchMangaParse(response: Response): PagedList = commonMangaParse(response) + + override fun popularMangaRequest(page: Int): Request = GET(baseUrl) + + override fun popularMangaParse(response: Response): PagedList = commonMangaParse(response) + + override fun mangaInfoRequest(url: String): Request = GET(url) + + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { + Jsoup.parse(response.body()!!.string()).let { + title = it.selectFirst("h1").text() + author = it.selectFirst(".author").text() + thumbnail_url = it.selectFirst(".other_card img").attr("src") + genre = it.selectFirst(".genre").text().replace(" ",", ") + description = it.selectFirst(".summary").text() + } + } + + override fun chaptersRequest(page: Int, url: String): Request = GET(url) + + override fun chaptersParse(response: Response): PagedList { + Jsoup.parse(response.body()!!.string()).let{ + val href = it.selectFirst("#_listUl a").attr("href") + val split = href.lastIndexOf("=") + 1 + val half = href.substring(0,split) + val ret = ArrayList() + for(i in href.substring(split).toInt() .. 1){ + ret.add(SChapter.create().apply { + name = i.toString() + url = half + i + }) + } + return PagedList(ret, false) + } + } + + override fun mangaPagesRequest(chapter: SChapter): Request = GET(chapter.url!!) + + override fun mangaPagesParse(response: Response): List { + val doc = Jsoup.parse(response.body()!!.string()) + return doc.select("#_viewerBox img").mapIndexed { i, node -> + MangaPage(i, "", node.attr("data-url")) + } + } + + override fun headersBuilder() = super.headersBuilder().add("Referer", baseUrl)!! + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") + + override fun getFilterList(): FilterList = FilterList() +} \ No newline at end of file diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Manhuatai.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaTai.kt similarity index 92% rename from app/src/main/java/top/rechinx/meow/core/source/internal/Manhuatai.kt rename to app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaTai.kt index cb43a13..5333e7a 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/Manhuatai.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaTai.kt @@ -6,7 +6,7 @@ import org.json.JSONObject import top.rechinx.meow.core.source.HttpSource import top.rechinx.meow.core.source.model.* -class Manhuatai:HttpSource() { +class ManHuaTai:HttpSource() { override val name = "漫画台" override val baseUrl = "http://getcomicinfo-globalapi.yyhao.com" @@ -75,10 +75,14 @@ class Manhuatai:HttpSource() { for(i in 0 until chapters.length()){ val chapter = chapters.getJSONObject(i) ret.add(SChapter.create().apply { - name = when(chapter.getInt("islock")) { - 1 -> "🔒" + chapter.getString("chapter_name") - else -> chapter.getString("chapter_name") - } + name = when(chapter.has("isbuy") && chapter.getInt("isbuy") == 1) { + true -> "💰" + else -> "" + } + when(chapter.getInt("islock")) { + 1 -> "🔒" + else -> "" + } + chapter.getString("chapter_name") + url = response.request().url().toString()+"&chapter="+i.toString() chapter_number = i.toString() date_updated = 1000 * chapter.getLong("create_date") @@ -105,9 +109,6 @@ class Manhuatai:HttpSource() { } } - override fun headersBuilder() - = super.headersBuilder().add("Referer", baseUrl)!! - override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") override fun getFilterList(): FilterList = FilterList() diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/Tencent.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/Tencent.kt index 4aa5d8f..b799f09 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/Tencent.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/Tencent.kt @@ -50,10 +50,10 @@ class Tencent:HttpSource() { thumbnail_url = it.selectFirst(".works-cover img").attr("src") author = it.selectFirst(".works-intro-digi em").text() // status = when(it.selectFirst(".comic_infor_status span").text()) { -//// "已完结" -> SManga.COMPLETED -//// "连载中" -> SManga.ONGOING -//// else -> SManga.UNKNOWN -//// } +// "已完结" -> SManga.COMPLETED +// "连载中" -> SManga.ONGOING +// else -> SManga.UNKNOWN +// } genre = it.select(".works-intro-tags a") .map{ node -> node.text() }.joinToString(", ") description = it.selectFirst(".works-intro-short").text() From f9eaaa94ab04b0a1843c2724e0e1c6d26e61a752 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Fri, 9 Aug 2019 19:02:30 +0800 Subject: [PATCH 18/27] fix --- .../main/java/top/rechinx/meow/core/source/internal/DongMan.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/DongMan.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/DongMan.kt index e831d01..c995f60 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/DongMan.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/DongMan.kt @@ -56,7 +56,7 @@ class DongMan:HttpSource() { val split = href.lastIndexOf("=") + 1 val half = href.substring(0,split) val ret = ArrayList() - for(i in href.substring(split).toInt() .. 1){ + for(i in href.substring(split).toInt() downTo 1){ ret.add(SChapter.create().apply { name = i.toString() url = half + i From 6356d0eb09fc346e14b8ea0ee52db2bafbc8c7f0 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 10 Aug 2019 11:52:33 +0800 Subject: [PATCH 19/27] replace u17 to http://app.u17.com --- .../rechinx/meow/core/source/SourceManager.kt | 5 +- .../rechinx/meow/core/source/internal/U17.kt | 156 +++++++++++------- .../meow/core/source/internal/U17www.kt | 95 +++++++++++ 3 files changed, 198 insertions(+), 58 deletions(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/U17www.kt diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index bb6dda3..17d38ba 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -41,10 +41,11 @@ class SourceManager(private val context: Context) { ManHuaLou(), Tohomh(), Bilibili(), - U17(), + //U17www(), Tencent(), ManHuaTai(), - DongMan() + DongMan(), + U17() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt index 3b9757e..37c8c3b 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt @@ -1,92 +1,136 @@ package top.rechinx.meow.core.source.internal -import android.util.Base64 import okhttp3.Request import okhttp3.Response import org.json.JSONObject -import org.jsoup.Jsoup import top.rechinx.meow.core.source.HttpSource import top.rechinx.meow.core.source.model.* class U17:HttpSource() { - override val name = "U17" - override val baseUrl = "http://www.u17.com" + override val baseUrl = "http://app.u17.com" private fun GET(url: String) = Request.Builder() .url(url) .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") .build() - override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request = GET("http://so.u17.com/all/$keyword/m0_p$page.html") - - override fun searchMangaParse(response: Response): PagedList { - val doc = Jsoup.parse(response.body()!!.string()) - val ret = doc.select(".comiclist li").map { node -> SManga.create().apply { - title = node.selectFirst("h3 a").text() - thumbnail_url = node.selectFirst("img").attr("src") - url = node.selectFirst("a").attr("href") - author = node.select("h3>a")?.text() - } } - return PagedList(ret, doc.selectFirst(".next") != null && doc.selectFirst(".next.over") == null) + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request + = GET("$baseUrl/v3/appV3_3/android/phone/search/searchResult?q=$keyword&page=$page") + + private fun commonMangaParse(response: Response): PagedList{ + val json = JSONObject(response.body()!!.string()) + val data = json.getJSONObject("data").getJSONObject("returnData") + val comics = data.getJSONArray("comics") + val ret = ArrayList() + for(i in 0 until comics.length()){ + ret.add(SManga.create().apply { + val manga = comics.getJSONObject(i) + title = manga.getString("name") + author = manga.getString("author") + thumbnail_url = manga.getString("cover") + + genre = manga.getJSONArray("tags").join(", ") + + url = when(manga.has("comicId")){ + true -> "$baseUrl/v3/appV3_3/android/phone/comic/detail_static_new?&comicid=${manga.getInt("comicId")}" + else -> "$baseUrl/v3/appV3_3/android/phone/comic/detail_static_new?&comicid=${manga.getInt("comic_id")}" + } + + description = manga.getString("description") + }) + } + return PagedList(ret, data.has("hasMore") && data.getBoolean("hasMore")) } - override fun popularMangaRequest(page: Int): Request = GET(baseUrl) + override fun searchMangaParse(response: Response): PagedList = commonMangaParse(response) - override fun popularMangaParse(response: Response): PagedList { - val doc = Jsoup.parse(response.body()!!.string()) - val ret = doc.select(".comic_all li").map { node -> SManga.create().apply { - title = node.selectFirst("a[title]").attr("title") - thumbnail_url = node.selectFirst("img").attr("xsrc") - url = node.selectFirst("a").attr("href") - } } - return PagedList(ret, doc.selectFirst(".next") != null && doc.selectFirst(".next.over") == null) - } + override fun popularMangaRequest(page: Int): Request + = GET("$baseUrl/v3/appV3_3/android/phone/list/conditionScreenlists?page=$page") + + override fun popularMangaParse(response: Response): PagedList = commonMangaParse(response) override fun mangaInfoRequest(url: String): Request = GET(url) override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { - Jsoup.parse(response.body()!!.string()).selectFirst(".comic_info").let { - title = it.selectFirst("h1").text() - thumbnail_url = it.selectFirst(".cover img").attr("src") - author = it.selectFirst(".author_info .info a").text() - status = when(it.selectFirst(".comic_infor_status span").text()) { - "已完结" -> SManga.COMPLETED - "连载中" -> SManga.ONGOING - else -> SManga.UNKNOWN - } - genre = it.select(".class_tag") - .map{ node -> node.text() }.joinToString(", ") - description = it.selectFirst(".words").text() + JSONObject(response.body()!!.string()) + .getJSONObject("data") + .getJSONObject("returnData") + .getJSONObject("comic") + .let { + title = it.getString("name") + thumbnail_url = it.getString("cover") + author = it.getJSONObject("author").getString("name") + status = when(it.getInt("series_status")) { + 1 -> SManga.COMPLETED + 0 -> SManga.ONGOING + else -> SManga.UNKNOWN + } + + genre = (it.getJSONArray("tagList").join(", ") + ", " + + it.getJSONArray("theme_ids").join(", ")).replace("\"","") + + description = it.getString("description") } } override fun chaptersRequest(page: Int, url: String): Request = GET(url) override fun chaptersParse(response: Response): PagedList { - val doc = Jsoup.parse(response.body()!!.string()) - val ret = doc.select("#chapter li").map { node -> SChapter.create().apply { - name = when(node.selectFirst("a").className()){ - "vip_chapter" -> "🔒" + node.text() - else -> node.text() - } - url = node.selectFirst("a").attr("href") - } } - return PagedList(ret.reversed(), false) + JSONObject(response.body()!!.string()) + .getJSONObject("data") + .getJSONObject("returnData") + .getJSONArray("chapter_list") + .let { + val ret = ArrayList() + for(i in it.length() downTo 0){ + val chapter = it.getJSONObject(i) + ret.add(SChapter.create().apply { + name = when(chapter.getInt("type")) { + 2 -> "🔒" + 3 -> "🔓" + else -> "" + } + chapter.getString("name") + url = chapter.getString("chapter_id") + chapter_number = chapter.getString("index") + date_updated = 1000 * chapter.getLong("pass_time") + }) + } + return PagedList(ret, false) + } } - override fun mangaPagesRequest(chapter: SChapter): Request = GET(chapter.url!!) + override fun mangaPagesRequest(chapter: SChapter): Request + = GET("$baseUrl/v3/appV3_3/android/phone/comic/chapterNew?chapter_id=${chapter.url}") override fun mangaPagesParse(response: Response): List { - val res = response.body()!!.string() - val list = JSONObject(Regex("image_list\\s*:\\s*(.*?\\}\\})").find(res)!!.groupValues[1]) - val ret = ArrayList() - var i = 0 - list.keys().forEach { - ret.add(MangaPage(i, "", String(Base64.decode(list.getJSONObject(it).getString("src"), Base64.NO_WRAP)))) - i++ - } - return ret + JSONObject(response.body()!!.string()) + .getJSONObject("data") + .getJSONObject("returnData") + .let{ + val ret = ArrayList() + + if(it.has("image_list")){ + val images = it.getJSONArray("image_list") + for(i in 0 until images.length()){ + ret.add(MangaPage(i, "", images.getJSONObject(i).getString("location"))) + } + } + if(it.has("free_image_list")){ + val images = it.getJSONArray("free_image_list") + for(i in 0 until images.length()){ + ret.add(MangaPage(i, "", images.getJSONObject(i).getString("location"))) + } + } + /*if(it.has("unlock_image")){ + val images = it.getJSONArray("unlock_image") + for(i in 0 until images.length()){ + ret.add(MangaPage(i, "", images.getJSONObject(i).getString("blur_image_url"))) + } + }*/ + + return ret + } } override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/U17www.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/U17www.kt new file mode 100644 index 0000000..9a26d0d --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/U17www.kt @@ -0,0 +1,95 @@ +package top.rechinx.meow.core.source.internal + +import android.util.Base64 +import okhttp3.Request +import okhttp3.Response +import org.json.JSONObject +import org.jsoup.Jsoup +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* + +class U17www:HttpSource() { + + override val name = "U17www" + override val baseUrl = "http://www.u17.com" + + private fun GET(url: String) = Request.Builder() + .url(url) + .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request = GET("http://so.u17.com/all/$keyword/m0_p$page.html") + + override fun searchMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".comiclist li").map { node -> SManga.create().apply { + title = node.selectFirst("h3 a").text() + thumbnail_url = node.selectFirst("img").attr("src") + url = node.selectFirst("a").attr("href") + author = node.select("h3>a")?.text() + } } + return PagedList(ret, doc.selectFirst(".next") != null && doc.selectFirst(".next.over") == null) + } + + override fun popularMangaRequest(page: Int): Request = GET(baseUrl) + + override fun popularMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".comic_all li").map { node -> SManga.create().apply { + title = node.selectFirst("a[title]").attr("title") + thumbnail_url = node.selectFirst("img").attr("xsrc") + url = node.selectFirst("a").attr("href") + } } + return PagedList(ret, doc.selectFirst(".next") != null && doc.selectFirst(".next.over") == null) + } + + override fun mangaInfoRequest(url: String): Request = GET(url) + + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { + Jsoup.parse(response.body()!!.string()).selectFirst(".comic_info").let { + title = it.selectFirst("h1").text() + thumbnail_url = it.selectFirst(".cover img").attr("src") + author = it.selectFirst(".author_info .info a").text() + status = when(it.selectFirst(".comic_infor_status span").text()) { + "已完结" -> SManga.COMPLETED + "连载中" -> SManga.ONGOING + else -> SManga.UNKNOWN + } + genre = it.select(".class_tag") + .map{ node -> node.text() }.joinToString(", ") + description = it.selectFirst(".words").text() + } + } + + override fun chaptersRequest(page: Int, url: String): Request = GET(url) + + override fun chaptersParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select("#chapter li").map { node -> SChapter.create().apply { + name = when(node.selectFirst("a").className()){ + "vip_chapter" -> "🔒" + node.text() + else -> node.text() + } + url = node.selectFirst("a").attr("href") + } } + return PagedList(ret.reversed(), false) + } + + override fun mangaPagesRequest(chapter: SChapter): Request = GET(chapter.url!!) + + override fun mangaPagesParse(response: Response): List { + val res = response.body()!!.string() + val list = JSONObject(Regex("image_list\\s*:\\s*(.*?\\}\\})").find(res)!!.groupValues[1]) + val ret = ArrayList() + var i = 0 + list.keys().forEach { + ret.add(MangaPage(i, "", String(Base64.decode(list.getJSONObject(it).getString("src"), Base64.NO_WRAP)))) + i++ + } + return ret + } + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Unused method was called somehow!") + + override fun getFilterList(): FilterList = FilterList() +} \ No newline at end of file From d60628b4c74713bf3ba7966fc60eff34395bdd61 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 10 Aug 2019 11:55:05 +0800 Subject: [PATCH 20/27] fix --- app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt index 37c8c3b..7b67b44 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/U17.kt @@ -83,7 +83,7 @@ class U17:HttpSource() { .getJSONArray("chapter_list") .let { val ret = ArrayList() - for(i in it.length() downTo 0){ + for(i in (it.length()-1) downTo 0){ val chapter = it.getJSONObject(i) ret.add(SChapter.create().apply { name = when(chapter.getInt("type")) { From 2b548344c7b25b95c00fca739de3ac38c0561203 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Wed, 14 Aug 2019 23:03:46 +0800 Subject: [PATCH 21/27] fix --- .../rechinx/meow/data/database/dao/ChapterDao.kt | 3 +++ .../top/rechinx/meow/ui/details/DetailPresenter.kt | 11 +++++++++++ .../top/rechinx/meow/ui/result/ResultPresenter.kt | 14 ++++++++------ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt b/app/src/main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt index 7ce1f6f..7ebfd72 100644 --- a/app/src/main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt +++ b/app/src/main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt @@ -24,6 +24,9 @@ interface ChapterDao { @Query("SELECT * FROM Chapter WHERE id = :chapterId") fun getChapter(chapterId: Long): Chapter? + @Query("DELETE FROM Chapter WHERE manga_id = :mangaId") + fun deleteChapters(mangaId: Long) + @Delete fun deleteChapters(list: List) diff --git a/app/src/main/java/top/rechinx/meow/ui/details/DetailPresenter.kt b/app/src/main/java/top/rechinx/meow/ui/details/DetailPresenter.kt index 3a729e9..743f58d 100644 --- a/app/src/main/java/top/rechinx/meow/ui/details/DetailPresenter.kt +++ b/app/src/main/java/top/rechinx/meow/ui/details/DetailPresenter.kt @@ -68,6 +68,7 @@ class DetailPresenter(val sourceId: Long, val url: String): BasePresenter networkToLocalChapter(chapter, manga?.id!!) } }.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -117,6 +118,7 @@ class DetailPresenter(val sourceId: Long, val url: String): BasePresenter(), KoinC try { if(it.list.isEmpty()) throw Exception() for(item in it.list) { - val manga = Manga() - manga.copyFrom(item) - manga.sourceId = source.id - manga.sourceName = source.name - emitter.onNext(manga) - Thread.sleep(Random().nextInt(200).toLong()) + if(item.title != null && item.title!!.contains(query)){ + val manga = Manga() + manga.copyFrom(item) + manga.sourceId = source.id + manga.sourceName = source.name + emitter.onNext(manga) + Thread.sleep(Random().nextInt(200).toLong()) + } } emitter.onComplete() } catch (e: Exception) { From a1561fb46f6bbfad872ad6a0b25825afa97c753d Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Thu, 15 Aug 2019 13:00:44 +0800 Subject: [PATCH 22/27] Revert "fix" This reverts commit 2b548344 --- .../top/rechinx/meow/ui/details/DetailPresenter.kt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/app/src/main/java/top/rechinx/meow/ui/details/DetailPresenter.kt b/app/src/main/java/top/rechinx/meow/ui/details/DetailPresenter.kt index 743f58d..3a729e9 100644 --- a/app/src/main/java/top/rechinx/meow/ui/details/DetailPresenter.kt +++ b/app/src/main/java/top/rechinx/meow/ui/details/DetailPresenter.kt @@ -68,7 +68,6 @@ class DetailPresenter(val sourceId: Long, val url: String): BasePresenter networkToLocalChapter(chapter, manga?.id!!) } }.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -118,7 +117,6 @@ class DetailPresenter(val sourceId: Long, val url: String): BasePresenter Date: Thu, 15 Aug 2019 13:01:16 +0800 Subject: [PATCH 23/27] Revert "fix" This reverts commit 2b548344 --- .../main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt b/app/src/main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt index 7ebfd72..7ce1f6f 100644 --- a/app/src/main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt +++ b/app/src/main/java/top/rechinx/meow/data/database/dao/ChapterDao.kt @@ -24,9 +24,6 @@ interface ChapterDao { @Query("SELECT * FROM Chapter WHERE id = :chapterId") fun getChapter(chapterId: Long): Chapter? - @Query("DELETE FROM Chapter WHERE manga_id = :mangaId") - fun deleteChapters(mangaId: Long) - @Delete fun deleteChapters(list: List) From 635e8756d3c5381f37959d1f21232f7c9067400e Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 9 Nov 2019 13:29:27 +0800 Subject: [PATCH 24/27] commit --- app/build.gradle | 36 ++++--- .../rechinx/meow/core/source/SourceManager.kt | 3 +- .../meow/core/source/internal/ManHuaDui.kt | 95 +++++++++++++++++++ app/src/main/res/layout/fragment_about.xml | 23 +++++ app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 2 + gradle/wrapper/gradle-wrapper.properties | 2 +- 7 files changed, 145 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt diff --git a/app/build.gradle b/app/build.gradle index b6892dd..160e461 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,21 +6,27 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' -def keystorePropertiesFile = rootProject.file(".travis/keystore.properties") -def keystoreProperties = new Properties() -keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) -def keyStoreFile = file(keystoreProperties['storeFileLocal']) -if (!keyStoreFile.exists()){ - keyStoreFile = file(keystoreProperties['storeFileCI']) -} +//def keystorePropertiesFile = rootProject.file(".travis/keystore.properties") +//def keystoreProperties = new Properties() +//keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +//def keyStoreFile = file(keystoreProperties['storeFileLocal']) +//if (!keyStoreFile.exists()){ +// keyStoreFile = file(keystoreProperties['storeFileCI']) +//} android { + lintOptions { + checkReleaseBuilds false + abortOnError false + } signingConfigs { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPwd'] - storeFile keyStoreFile - storePassword keystoreProperties['storePwd'] + myConfig { + storeFile file(RELEASE_STORE_FILE) + storePassword RELEASE_STORE_PASSWORD + keyAlias RELEASE_KEY_ALIAS + keyPassword RELEASE_KEY_PASSWORD + v1SigningEnabled true + v2SigningEnabled true } } compileSdkVersion 28 @@ -28,8 +34,8 @@ android { applicationId "top.rechinx.meow" minSdkVersion 16 targetSdkVersion 27 - versionCode 6 - versionName "1.0.6" + versionCode 8 + versionName "1.0.8" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true multiDexEnabled true @@ -38,7 +44,7 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release + signingConfig signingConfigs.myConfig } debug { applicationIdSuffix ".debug" diff --git a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt index 17d38ba..f799ba7 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/SourceManager.kt @@ -45,7 +45,8 @@ class SourceManager(private val context: Context) { Tencent(), ManHuaTai(), DongMan(), - U17() + U17(), + ManHuaDui() //Shuhui(), //EHentai() ) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt new file mode 100644 index 0000000..a8e2a22 --- /dev/null +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt @@ -0,0 +1,95 @@ +package top.rechinx.meow.core.source.internal + +import okhttp3.Request +import okhttp3.Response + +import org.jsoup.Jsoup + +import top.rechinx.meow.core.source.HttpSource +import top.rechinx.meow.core.source.model.* + + +class ManHuaDui:HttpSource() { + + override val name: String = "漫画堆" + + override val baseUrl: String = "https://m.manhuadui.com" + + private fun GET(url: String) = Request.Builder() + .url(url) + .addHeader("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Mobile Safari/537.36") + .build() + + override fun searchMangaRequest(keyword: String, page: Int, filters: FilterList): Request + = GET("https://m.manhuadui.com/search/?keywords=$keyword&page=$page") + + override fun searchMangaParse(response: Response): PagedList = commonMangaParse(response) + + private fun commonMangaParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select(".itemBox,.list-comic").map { node -> SManga.create().apply { + title = node.selectFirst(".title").text() + thumbnail_url = node.selectFirst("img").attr("src") + url = node.selectFirst(".title").attr("href") + description = node.selectFirst(".pd,.date").text() + author = node.selectFirst(".txtItme").text() + } } + return PagedList(ret, true) + } + + override fun popularMangaRequest(page: Int): Request = GET("https://m.manhuadui.com/update/$page/") + + override fun popularMangaParse(response: Response): PagedList = commonMangaParse(response) + + override fun mangaInfoRequest(url: String): Request = GET(url) + + override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { + val dom = Jsoup.parse(response.body()!!.string()) + title = dom.selectFirst("h1").text() +// thumbnail_url = infoElement.selectFirst(".cover img").attr("src") +// author = infoElement.selectFirst(".subtitle").text().substringAfter(":").trim() +// status = when(infoElement.selectFirst("span:nth-of-type(1) span").text()) { +// "连载中" -> SManga.ONGOING +// "完结" -> SManga.COMPLETED +// else -> SManga.UNKNOWN +// } +// genre = infoElement.select(".tip a") +// .map{ node -> node.text() }.joinToString(", ") +// description = infoElement.select("p.content").text() + } + + override fun chaptersRequest(page: Int, url: String): Request = GET(url) + + override fun chaptersParse(response: Response): PagedList { + val doc = Jsoup.parse(response.body()!!.string()) + val ret = doc.select("#chapter-list-1 a").map { node -> SChapter.create().apply { + name = node.text() + url = node.attr("href") + } } + return PagedList(ret, false) + } + + override fun mangaPagesRequest(chapter: SChapter): Request = GET(chapter.url!!) + + override fun mangaPagesParse(response: Response): List { + val doc = Jsoup.parse(response.body()!!.string()) + val info = doc.select(".BarTit").text() + val reg = Regex("\\d+/(\\d+)").find(info) + if(reg != null){ + val len = reg.groupValues[1].toInt() + val ret = ArrayList(len) + val sp = response.request().url().url().toString().split(".html") + for ( i in 1 .. len){ + ret.add(MangaPage(i, "${sp[0]}-${i + 1}.html", "")) + } + return ret + } + return ArrayList() + } + + override fun imageUrlParse(response: Response): String + = Jsoup.parse(response.body()!!.string()).select("mip-img").attr("src") + + override fun getFilterList(): FilterList = FilterList() + +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml index 3721c19..2e542ad 100644 --- a/app/src/main/res/layout/fragment_about.xml +++ b/app/src/main/res/layout/fragment_about.xml @@ -85,5 +85,28 @@ android:textColor="?android:attr/textColorSecondary" android:text="@string/about_resource_url"/> + + + + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index d45501b..37e459b 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -22,6 +22,7 @@ 检查更新 点击检查更新 源代码 + 分支 加载更多章节 正在解析 暂停中 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7362979..0033c04 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,6 +26,8 @@ Click to check update Source code https://github.com/ReChinX/Meow + Fork + https://github.com/mabDc/Meow Ongoing Completed Unknown diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 418447c..7c6673f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip From f530f07230edd777d58c19316b2b90cd30267c10 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 9 Nov 2019 16:27:52 +0800 Subject: [PATCH 25/27] commit --- app/gradle.properties | 5 +++++ app/key.properties.jks | Bin 0 -> 2248 bytes build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 app/gradle.properties create mode 100644 app/key.properties.jks diff --git a/app/gradle.properties b/app/gradle.properties new file mode 100644 index 0000000..a5af447 --- /dev/null +++ b/app/gradle.properties @@ -0,0 +1,5 @@ +# RELEASE_STORE_FILE = "..\\key.properties.jks" +RELEASE_STORE_FILE=.\\key.properties.jks +RELEASE_KEY_PASSWORD=android +RELEASE_KEY_ALIAS=key0 +RELEASE_STORE_PASSWORD=android \ No newline at end of file diff --git a/app/key.properties.jks b/app/key.properties.jks new file mode 100644 index 0000000000000000000000000000000000000000..d0f08ec92dddbf6c7cb6da22dae37ce2f1741451 GIT binary patch literal 2248 zcmc(g`#aN(8^`zAX0$bwQ{*hdWFJf-wWgf&tjHnBSwtCT&FN`UBSOw{K14aCn#zbd z70G!v6(VOHCQ3pNzP`_MeXr~3FZlj&|M0qhxUc(q-}m)?Z}K*I5C{aiUBKT3_wxz` zx50g7;(G@K!UqAP;D3RF2qXppzyWpWE&$+zz@y;v@4gmZoGN!^2xP|IUgX?DktC=ia*}RQG~`wVqoV$! z<8J1LRq3h9sm0XXEV%5+P!C}zLSp9$PN~mW{Y%9O0$0J&{{csDo{wW&(tDLf*vWb6 zi@ItckYqV|d2r?Hi1)CP0xy54jxe*}dAz~Qx(IFNW*E~-3z*ljC*}8hTnHXFk3KwP z`soeEWZJj*y_;guh@RQi)2)~2#1>=IYBl8}qv}@ndK?k`7M>}_b@byyJLz9SO7-lD zB$;SW8ul|&jv6TN^Ghe07qcAc@CnS(VzED$5tHKc&AVKN#-(Ff+0W1GZ4voUwskdm zA2C|%om9>Hy6^mL_@h!#y;j(oYPtc1X77e>N{fotuuvBJsiH3GW9oe!S({YMW>%Ha zY4JvH-#YjzDVra^tdX~NP>6lLGPm@Hh^A%Ej6k*RxW{0Y14^#pxxZn^C$p-m zJpW1k$jSk!k@c=pMo{B@mjR-o)NBt)(V{a8J@}!7=qO4nI9TJ?Q6poFqbnu{siZ?; zsk_s;)a;8_Rjql!=oV7nlwEj6_S3d0ldB4Wm5=RC>P6V}hg5Ox5h21Qs~BEkSH~`O z3Keq&mE78e|ID%&3mg5EW3d`+-%Q(5GQAsO;xMep1^sqQd?V(O(%TS>)yWg5O!n@; zr_LUN@G(OsC`Zu3TX=DvKwc2P=(*C)qbC9nr3pk^yP;W%-;FX&^EQG#`r<#2l@mzu z%V*M8n{*SfH>&p}=aZd5mc%n4<6;UOIkd=ScsCqvZ?f}CnVn~yYOo`4&NqciE#l&3yKJs1a}?z4e==_VY;!p&D?KsNZ1IAb7qb@@_hxC83NhE0!jAXvdyi)bTIHll z1=AAL!rFHt)Dnk_&z%l|U(=fyCLvw3jRjwYckj>jUJF}yg4HMsIt%qu4EyS?)MQe6 zW+umEZXVH=I@Y41AeaxyO~_EG9Zms<+d z;8!rn=lGTVk5*hnoms4cO_z`K$E7Ic-gIpEOBT zy*rN9eot?7Bi`0}a(hJh9ijG!M*^Dhv3FrnWj&2lA7XSvfEre~pRZl zf_fLipa2vKw?fgSK{R5AdbC;ePc#6awhc2tYbS_Az--|N5ty5s+y6-5H{$<|kiQY? zA5sNX{yPOGBIgqv9AJROQmIr;4}bSdByX~&2kA04)Xm>JG{h4N%1WTM4uLpr9HQC_rdCOaLS_3IHHa8}TZIqk86wRmL)`eaqI@ zrdZf7&Cj06&)*5Ft0+0Qxp(tK;L={{V)~UfhK= zc8{k@_N>*8+o#{NK#<8=rFIP$RMJS%bLk2yvQC+=Njj5pFMB4`(A}zmNsrJseK4IV zDoB5Gv>H$6Yf92%(WT_b&M)B%ZZK{?OFmt8OUA^wEi5MI5w1b}kC7fWbH#*IFnLLa zCNfgl8S&f#6J0U`+u&xo#uCsJ6i|7w&;ZysL`bE|{F5#|{ zqC%y=UMh36mGbp(hBVFu_**wRTc%l4N?;Kk&HijS`?t151R&|^8&7dgN3Ld#l}=&Xp35c|hN4?}@>2_Ak-O(_ zwijd!GIsi;z`o+zTHOG*{w}M4;(;e?Qezc&S7+J16iwf*St6$TaP4k$T@4>|FE6-L z@khxh>;3%dKh0wK}0|V{Nv64LEDt6FC4)U`*Lvd$bXweVM+A0&iX5@&YIt zZ~pj|s`;?@-HSC}h3gkqI*aOy%-m vBKfN?er~YkDB|G$Z;9_DQg3k+5FB!eA5Kwn`lONoUIAy(h?lQt+h_a-yiM7! literal 0 HcmV?d00001 diff --git a/build.gradle b/build.gradle index 95ce6f5..a114b43 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.10' + ext.kotlin_version = '1.3.50' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0' + classpath 'com.android.tools.build:gradle:3.5.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7c6673f..ebd6045 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Feb 07 14:42:10 CST 2019 +#Sat Nov 09 14:44:07 CST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip From 27e41a08ccb2e725a9be62e959ab369b5316f19d Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 9 Nov 2019 16:41:31 +0800 Subject: [PATCH 26/27] fix manhuadui --- .../top/rechinx/meow/core/source/internal/ManHuaDui.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt index a8e2a22..41afdcf 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt @@ -46,8 +46,8 @@ class ManHuaDui:HttpSource() { override fun mangaInfoParse(response: Response): SManga = SManga.create().apply { val dom = Jsoup.parse(response.body()!!.string()) title = dom.selectFirst("h1").text() -// thumbnail_url = infoElement.selectFirst(".cover img").attr("src") -// author = infoElement.selectFirst(".subtitle").text().substringAfter(":").trim() + thumbnail_url = dom.selectFirst("#Cover img").attr("src") + author = dom.selectFirst(".txtItme").text().substringAfter(":").trim() // status = when(infoElement.selectFirst("span:nth-of-type(1) span").text()) { // "连载中" -> SManga.ONGOING // "完结" -> SManga.COMPLETED @@ -55,7 +55,7 @@ class ManHuaDui:HttpSource() { // } // genre = infoElement.select(".tip a") // .map{ node -> node.text() }.joinToString(", ") -// description = infoElement.select("p.content").text() + description = dom.select("#full-des").text() } override fun chaptersRequest(page: Int, url: String): Request = GET(url) @@ -64,7 +64,7 @@ class ManHuaDui:HttpSource() { val doc = Jsoup.parse(response.body()!!.string()) val ret = doc.select("#chapter-list-1 a").map { node -> SChapter.create().apply { name = node.text() - url = node.attr("href") + url = "https://m.manhuadui.com${node.attr("href")}" } } return PagedList(ret, false) } @@ -80,7 +80,7 @@ class ManHuaDui:HttpSource() { val ret = ArrayList(len) val sp = response.request().url().url().toString().split(".html") for ( i in 1 .. len){ - ret.add(MangaPage(i, "${sp[0]}-${i + 1}.html", "")) + ret.add(MangaPage(i, "${sp[0]}-$i.html", "")) } return ret } From f98d9ce3d5df982b12cd684fc0f493811cb5dd06 Mon Sep 17 00:00:00 2001 From: mabdc <747455334@qq.com> Date: Sat, 9 Nov 2019 17:54:47 +0800 Subject: [PATCH 27/27] fix manhuadui --- .../java/top/rechinx/meow/core/source/internal/ManHuaDui.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt index 41afdcf..f9e0057 100644 --- a/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt +++ b/app/src/main/java/top/rechinx/meow/core/source/internal/ManHuaDui.kt @@ -66,7 +66,7 @@ class ManHuaDui:HttpSource() { name = node.text() url = "https://m.manhuadui.com${node.attr("href")}" } } - return PagedList(ret, false) + return PagedList(ret.reversed(), false) } override fun mangaPagesRequest(chapter: SChapter): Request = GET(chapter.url!!)