Fix network unsubscription crashes, refactor network methods

This commit is contained in:
len 2016-05-27 16:52:44 +02:00
parent 79bb207a8d
commit efd36388b0
14 changed files with 113 additions and 121 deletions

View File

@ -91,7 +91,6 @@ kapt {
dependencies { dependencies {
final SUPPORT_LIBRARY_VERSION = '23.4.0' final SUPPORT_LIBRARY_VERSION = '23.4.0'
final DAGGER_VERSION = '2.4' final DAGGER_VERSION = '2.4'
final OKHTTP_VERSION = '3.2.0'
final RETROFIT_VERSION = '2.0.2' final RETROFIT_VERSION = '2.0.2'
final NUCLEUS_VERSION = '3.0.0' final NUCLEUS_VERSION = '3.0.0'
final STORIO_VERSION = '1.8.0' final STORIO_VERSION = '1.8.0'
@ -118,7 +117,7 @@ dependencies {
compile 'com.f2prateek.rx.preferences:rx-preferences:1.0.1' compile 'com.f2prateek.rx.preferences:rx-preferences:1.0.1'
// Network client // Network client
compile "com.squareup.okhttp3:okhttp:$OKHTTP_VERSION" compile "com.squareup.okhttp3:okhttp:3.3.0"
// REST // REST
compile "com.squareup.retrofit2:retrofit:$RETROFIT_VERSION" compile "com.squareup.retrofit2:retrofit:$RETROFIT_VERSION"
@ -141,7 +140,7 @@ dependencies {
compile 'com.jakewharton:disklrucache:2.0.2' compile 'com.jakewharton:disklrucache:2.0.2'
// Parse HTML // Parse HTML
compile 'org.jsoup:jsoup:1.9.1' compile 'org.jsoup:jsoup:1.9.2'
// Changelog // Changelog
compile 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0' compile 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0'
@ -176,9 +175,7 @@ dependencies {
compile 'eu.davidea:flexible-adapter:4.2.0' compile 'eu.davidea:flexible-adapter:4.2.0'
compile 'com.nononsenseapps:filepicker:2.5.2' compile 'com.nononsenseapps:filepicker:2.5.2'
compile 'com.github.amulyakhare:TextDrawable:558677e' compile 'com.github.amulyakhare:TextDrawable:558677e'
compile('com.github.afollestad.material-dialogs:core:0.8.5.5@aar') { compile 'com.afollestad.material-dialogs:core:0.8.5.9'
transitive = true
}
// Tests // Tests
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'

View File

@ -28,7 +28,7 @@ class AppGlideModule : GlideModule {
override fun registerComponents(context: Context, glide: Glide) { override fun registerComponents(context: Context, glide: Glide) {
App.get(context).component.inject(this) App.get(context).component.inject(this)
glide.register(GlideUrl::class.java, InputStream::class.java, glide.register(GlideUrl::class.java, InputStream::class.java,
OkHttpUrlLoader.Factory(networkHelper.defaultClient)) OkHttpUrlLoader.Factory(networkHelper.client))
glide.register(Manga::class.java, InputStream::class.java, MangaModelLoader.Factory()) glide.register(Manga::class.java, InputStream::class.java, MangaModelLoader.Factory())
} }
} }

View File

@ -6,8 +6,8 @@ import android.util.Xml
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.MangaSync import eu.kanade.tachiyomi.data.database.models.MangaSync
import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService
import eu.kanade.tachiyomi.data.network.get import eu.kanade.tachiyomi.data.network.GET
import eu.kanade.tachiyomi.data.network.post import eu.kanade.tachiyomi.data.network.POST
import eu.kanade.tachiyomi.util.selectInt import eu.kanade.tachiyomi.util.selectInt
import eu.kanade.tachiyomi.util.selectText import eu.kanade.tachiyomi.util.selectText
import okhttp3.* import okhttp3.*
@ -65,7 +65,8 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
override fun login(username: String, password: String): Observable<Boolean> { override fun login(username: String, password: String): Observable<Boolean> {
createHeaders(username, password) createHeaders(username, password)
return networkService.request(get(getLoginUrl(), headers)) return networkService.request(GET(getLoginUrl(), headers))
.doOnNext { it.close() }
.map { it.code() == 200 } .map { it.code() == 200 }
} }
@ -77,7 +78,7 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
} }
fun search(query: String): Observable<List<MangaSync>> { fun search(query: String): Observable<List<MangaSync>> {
return networkService.request(get(getSearchUrl(query), headers)) return networkService.request(GET(getSearchUrl(query), headers))
.map { Jsoup.parse(it.body().string()) } .map { Jsoup.parse(it.body().string()) }
.flatMap { Observable.from(it.select("entry")) } .flatMap { Observable.from(it.select("entry")) }
.filter { it.select("type").text() != "Novel" } .filter { it.select("type").text() != "Novel" }
@ -102,7 +103,7 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
// MAL doesn't support score with decimals // MAL doesn't support score with decimals
fun getList(): Observable<List<MangaSync>> { fun getList(): Observable<List<MangaSync>> {
return networkService.request(get(getListUrl(username), headers), networkService.forceCacheClient) return networkService.request(GET(getListUrl(username), headers), networkService.forceCacheClient)
.map { Jsoup.parse(it.body().string()) } .map { Jsoup.parse(it.body().string()) }
.flatMap { Observable.from(it.select("manga")) } .flatMap { Observable.from(it.select("manga")) }
.map { .map {
@ -130,7 +131,7 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
if (manga.total_chapters != 0 && manga.last_chapter_read == manga.total_chapters) { if (manga.total_chapters != 0 && manga.last_chapter_read == manga.total_chapters) {
manga.status = COMPLETED manga.status = COMPLETED
} }
networkService.request(post(getUpdateUrl(manga), headers, getMangaPostPayload(manga))) networkService.request(POST(getUpdateUrl(manga), headers, getMangaPostPayload(manga)))
} }
} }
@ -144,7 +145,7 @@ class MyAnimeList(private val context: Context, id: Int) : MangaSyncService(cont
override fun add(manga: MangaSync): Observable<Response> { override fun add(manga: MangaSync): Observable<Response> {
return Observable.defer { return Observable.defer {
networkService.request(post(getAddUrl(manga), headers, getMangaPostPayload(manga))) networkService.request(POST(getAddUrl(manga), headers, getMangaPostPayload(manga)))
} }
} }

View File

@ -22,7 +22,7 @@ class CloudflareInterceptor(private val cookies: PersistentCookieStore) : Interc
// Check if we already solved a challenge // Check if we already solved a challenge
if (response.code() != 502 && if (response.code() != 502 &&
cookies.get(response.request().url()).find { it.name() == "cf_clearance" } != null) { cookies.get(response.request().url()).any { it.name() == "cf_clearance" }) {
return response return response
} }
@ -72,7 +72,7 @@ class CloudflareInterceptor(private val cookies: PersistentCookieStore) : Interc
.toString() .toString()
val referer = originalRequest.url().toString() val referer = originalRequest.url().toString()
return get(url, originalRequest.headers().newBuilder().add("Referer", referer).build()) return GET(url, originalRequest.headers().newBuilder().add("Referer", referer).build())
} finally { } finally {
duktape.close() duktape.close()
} }

View File

@ -1,12 +1,12 @@
package eu.kanade.tachiyomi.data.network package eu.kanade.tachiyomi.data.network
import android.content.Context import android.content.Context
import okhttp3.* import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import rx.Observable import rx.Observable
import rx.subscriptions.Subscriptions
import timber.log.Timber
import java.io.File import java.io.File
import java.io.IOException
class NetworkHelper(context: Context) { class NetworkHelper(context: Context) {
@ -16,74 +16,30 @@ class NetworkHelper(context: Context) {
private val cookieManager = PersistentCookieJar(context) private val cookieManager = PersistentCookieJar(context)
val defaultClient = OkHttpClient.Builder() val client = OkHttpClient.Builder()
.cookieJar(cookieManager) .cookieJar(cookieManager)
.cache(Cache(cacheDir, cacheSize)) .cache(Cache(cacheDir, cacheSize))
.build() .build()
val forceCacheClient = defaultClient.newBuilder() val forceCacheClient = client.newBuilder()
.addNetworkInterceptor({ chain -> .addNetworkInterceptor { chain ->
val originalResponse = chain.proceed(chain.request()) val originalResponse = chain.proceed(chain.request())
originalResponse.newBuilder() originalResponse.newBuilder()
.removeHeader("Pragma") .removeHeader("Pragma")
.header("Cache-Control", "max-age=" + 600) .header("Cache-Control", "max-age=600")
.build() .build()
}) }
.build() .build()
val cloudflareClient = defaultClient.newBuilder() val cloudflareClient = client.newBuilder()
.addInterceptor(CloudflareInterceptor(cookies)) .addInterceptor(CloudflareInterceptor(cookies))
.build() .build()
val cookies: PersistentCookieStore val cookies: PersistentCookieStore
get() = cookieManager.store get() = cookieManager.store
fun request(request: Request, client: OkHttpClient = defaultClient): Observable<Response> { fun request(request: Request, client: OkHttpClient = this.client): Observable<Response> {
return Observable.create { subscriber -> return client.newCall(request).asObservable()
val call = client.newCall(request)
subscriber.add(Subscriptions.create {
call.cancel()
Timber.i("Cancel call on thread ${Thread.currentThread().id}")
})
call.enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
if (!subscriber.isUnsubscribed) {
subscriber.add(Subscriptions.create {
response.body().close()
Timber.i("Close body on thread ${Thread.currentThread().id}")
})
subscriber.onNext(response)
Timber.i("Emit response on thread ${Thread.currentThread().id}")
subscriber.onCompleted()
}
}
override fun onFailure(call: Call, error: IOException) {
if (!subscriber.isUnsubscribed) {
subscriber.onError(error)
}
}
})
}
}
fun requestBodyProgress(request: Request, listener: ProgressListener): Observable<Response> {
return Observable.fromCallable { requestBodyProgressBlocking(request, listener) }
}
fun requestBodyProgressBlocking(request: Request, listener: ProgressListener): Response {
val progressClient = defaultClient.newBuilder()
.cache(null)
.addNetworkInterceptor { chain ->
val originalResponse = chain.proceed(chain.request())
originalResponse.newBuilder()
.body(ProgressResponseBody(originalResponse.body(), listener))
.build()
}
.build()
return progressClient.newCall(request).execute()
} }
} }

View File

@ -0,0 +1,41 @@
package eu.kanade.tachiyomi.data.network
import okhttp3.Call
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import rx.Observable
import rx.subscriptions.Subscriptions
import java.io.IOException
fun Call.asObservable(): Observable<Response> {
return Observable.create { subscriber ->
subscriber.add(Subscriptions.create { cancel() })
try {
val response = execute()
if (!subscriber.isUnsubscribed) {
subscriber.onNext(response)
subscriber.onCompleted()
}
} catch (error: IOException) {
if (!subscriber.isUnsubscribed) {
subscriber.onError(error)
}
}
}
}
fun OkHttpClient.newCallWithProgress(request: Request, listener: ProgressListener): Call {
val progressClient = newBuilder()
.cache(null)
.addNetworkInterceptor { chain ->
val originalResponse = chain.proceed(chain.request())
originalResponse.newBuilder()
.body(ProgressResponseBody(originalResponse.body(), listener))
.build()
}
.build()
return progressClient.newCall(request)
}

View File

@ -70,6 +70,6 @@ class PersistentCookieStore(context: Context) {
return cookieMap[url].orEmpty().filter { !it.hasExpired() } return cookieMap[url].orEmpty().filter { !it.hasExpired() }
} }
fun Cookie.hasExpired() = System.currentTimeMillis() >= expiresAt() private fun Cookie.hasExpired() = System.currentTimeMillis() >= expiresAt()
} }

View File

@ -7,8 +7,7 @@ private val DEFAULT_CACHE_CONTROL = CacheControl.Builder().maxAge(10, MINUTES).b
private val DEFAULT_HEADERS = Headers.Builder().build() private val DEFAULT_HEADERS = Headers.Builder().build()
private val DEFAULT_BODY: RequestBody = FormBody.Builder().build() private val DEFAULT_BODY: RequestBody = FormBody.Builder().build()
@JvmOverloads fun GET(url: String,
fun get(url: String,
headers: Headers = DEFAULT_HEADERS, headers: Headers = DEFAULT_HEADERS,
cache: CacheControl = DEFAULT_CACHE_CONTROL): Request { cache: CacheControl = DEFAULT_CACHE_CONTROL): Request {
@ -19,8 +18,7 @@ fun get(url: String,
.build() .build()
} }
@JvmOverloads fun POST(url: String,
fun post(url: String,
headers: Headers = DEFAULT_HEADERS, headers: Headers = DEFAULT_HEADERS,
body: RequestBody = DEFAULT_BODY, body: RequestBody = DEFAULT_BODY,
cache: CacheControl = DEFAULT_CACHE_CONTROL): Request { cache: CacheControl = DEFAULT_CACHE_CONTROL): Request {

View File

@ -5,8 +5,10 @@ import eu.kanade.tachiyomi.App
import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.network.GET
import eu.kanade.tachiyomi.data.network.NetworkHelper import eu.kanade.tachiyomi.data.network.NetworkHelper
import eu.kanade.tachiyomi.data.network.get import eu.kanade.tachiyomi.data.network.asObservable
import eu.kanade.tachiyomi.data.network.newCallWithProgress
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.Language import eu.kanade.tachiyomi.data.source.Language
import eu.kanade.tachiyomi.data.source.Source import eu.kanade.tachiyomi.data.source.Source
@ -57,7 +59,7 @@ abstract class OnlineSource(context: Context) : Source {
* Default network client for doing requests. * Default network client for doing requests.
*/ */
open val client: OkHttpClient open val client: OkHttpClient
get() = network.defaultClient get() = network.client
init { init {
// Inject dependencies. // Inject dependencies.
@ -114,7 +116,7 @@ abstract class OnlineSource(context: Context) : Source {
if (page.page == 1) { if (page.page == 1) {
page.url = popularMangaInitialUrl() page.url = popularMangaInitialUrl()
} }
return get(page.url, headers) return GET(page.url, headers)
} }
/** /**
@ -159,7 +161,7 @@ abstract class OnlineSource(context: Context) : Source {
if (page.page == 1) { if (page.page == 1) {
page.url = searchMangaInitialUrl(query) page.url = searchMangaInitialUrl(query)
} }
return get(page.url, headers) return GET(page.url, headers)
} }
/** /**
@ -201,7 +203,7 @@ abstract class OnlineSource(context: Context) : Source {
* @param manga the manga to be updated. * @param manga the manga to be updated.
*/ */
open protected fun mangaDetailsRequest(manga: Manga): Request { open protected fun mangaDetailsRequest(manga: Manga): Request {
return get(baseUrl + manga.url, headers) return GET(baseUrl + manga.url, headers)
} }
/** /**
@ -236,7 +238,7 @@ abstract class OnlineSource(context: Context) : Source {
* @param manga the manga to look for chapters. * @param manga the manga to look for chapters.
*/ */
open protected fun chapterListRequest(manga: Manga): Request { open protected fun chapterListRequest(manga: Manga): Request {
return get(baseUrl + manga.url, headers) return GET(baseUrl + manga.url, headers)
} }
/** /**
@ -281,7 +283,7 @@ abstract class OnlineSource(context: Context) : Source {
* @param chapter the chapter whose page list has to be fetched * @param chapter the chapter whose page list has to be fetched
*/ */
open protected fun pageListRequest(chapter: Chapter): Request { open protected fun pageListRequest(chapter: Chapter): Request {
return get(baseUrl + chapter.url, headers) return GET(baseUrl + chapter.url, headers)
} }
/** /**
@ -321,7 +323,7 @@ abstract class OnlineSource(context: Context) : Source {
* @param page the chapter whose page list has to be fetched * @param page the chapter whose page list has to be fetched
*/ */
open protected fun imageUrlRequest(page: Page): Request { open protected fun imageUrlRequest(page: Page): Request {
return get(page.url, headers) return GET(page.url, headers)
} }
/** /**
@ -347,11 +349,12 @@ abstract class OnlineSource(context: Context) : Source {
* *
* @param page the page whose source image has to be downloaded. * @param page the page whose source image has to be downloaded.
*/ */
fun imageResponse(page: Page): Observable<Response> = network fun imageResponse(page: Page): Observable<Response> = client
.requestBodyProgress(imageRequest(page), page) .newCallWithProgress(imageRequest(page), page)
.asObservable()
.doOnNext { .doOnNext {
if (!it.isSuccessful) { if (!it.isSuccessful) {
it.body().close() it.close()
throw RuntimeException("Not a valid response") throw RuntimeException("Not a valid response")
} }
} }
@ -363,7 +366,7 @@ abstract class OnlineSource(context: Context) : Source {
* @param page the chapter whose page list has to be fetched * @param page the chapter whose page list has to be fetched
*/ */
open protected fun imageRequest(page: Page): Request { open protected fun imageRequest(page: Page): Request {
return get(page.imageUrl, headers) return GET(page.imageUrl, headers)
} }
/** /**

View File

@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.data.source.online
import android.content.Context import android.content.Context
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.network.get import eu.kanade.tachiyomi.data.network.GET
import eu.kanade.tachiyomi.data.network.post import eu.kanade.tachiyomi.data.network.POST
import eu.kanade.tachiyomi.data.source.getLanguages import eu.kanade.tachiyomi.data.source.getLanguages
import eu.kanade.tachiyomi.data.source.model.MangasPage import eu.kanade.tachiyomi.data.source.model.MangasPage
import eu.kanade.tachiyomi.data.source.model.Page import eu.kanade.tachiyomi.data.source.model.Page
@ -32,7 +32,7 @@ class YamlOnlineSource(context: Context, mappings: Map<*, *>) : OnlineSource(con
override val client = when(map.client) { override val client = when(map.client) {
"cloudflare" -> network.cloudflareClient "cloudflare" -> network.cloudflareClient
else -> network.defaultClient else -> network.client
} }
override val id = map.id.let { override val id = map.id.let {
@ -44,8 +44,8 @@ class YamlOnlineSource(context: Context, mappings: Map<*, *>) : OnlineSource(con
page.url = popularMangaInitialUrl() page.url = popularMangaInitialUrl()
} }
return when (map.popular.method?.toLowerCase()) { return when (map.popular.method?.toLowerCase()) {
"post" -> post(page.url, headers, map.popular.createForm()) "post" -> POST(page.url, headers, map.popular.createForm())
else -> get(page.url, headers) else -> GET(page.url, headers)
} }
} }
@ -74,8 +74,8 @@ class YamlOnlineSource(context: Context, mappings: Map<*, *>) : OnlineSource(con
page.url = searchMangaInitialUrl(query) page.url = searchMangaInitialUrl(query)
} }
return when (map.search.method?.toLowerCase()) { return when (map.search.method?.toLowerCase()) {
"post" -> post(page.url, headers, map.search.createForm()) "post" -> POST(page.url, headers, map.search.createForm())
else -> get(page.url, headers) else -> GET(page.url, headers)
} }
} }

View File

@ -5,8 +5,8 @@ import android.net.Uri
import android.text.Html import android.text.Html
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.network.get import eu.kanade.tachiyomi.data.network.GET
import eu.kanade.tachiyomi.data.network.post import eu.kanade.tachiyomi.data.network.POST
import eu.kanade.tachiyomi.data.source.EN import eu.kanade.tachiyomi.data.source.EN
import eu.kanade.tachiyomi.data.source.Language import eu.kanade.tachiyomi.data.source.Language
import eu.kanade.tachiyomi.data.source.model.MangasPage import eu.kanade.tachiyomi.data.source.model.MangasPage
@ -20,7 +20,6 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.net.URI import java.net.URI
import java.net.URISyntaxException
import java.text.ParseException import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -58,12 +57,12 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex
override fun mangaDetailsRequest(manga: Manga): Request { override fun mangaDetailsRequest(manga: Manga): Request {
val mangaId = manga.url.substringAfterLast("r") val mangaId = manga.url.substringAfterLast("r")
return get("$baseUrl/comic_pop?id=$mangaId", headers) return GET("$baseUrl/comic_pop?id=$mangaId", headers)
} }
override fun pageListRequest(chapter: Chapter): Request { override fun pageListRequest(chapter: Chapter): Request {
val id = chapter.url.substringAfterLast("#") val id = chapter.url.substringAfterLast("#")
return get("$baseUrl/areader?id=$id&p=1", headers) return GET("$baseUrl/areader?id=$id&p=1", headers)
} }
override fun imageUrlRequest(page: Page): Request { override fun imageUrlRequest(page: Page): Request {
@ -71,7 +70,7 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex
val start = pageUrl.indexOf("#") + 1 val start = pageUrl.indexOf("#") + 1
val end = pageUrl.indexOf("_", start) val end = pageUrl.indexOf("_", start)
val id = pageUrl.substring(start, end) val id = pageUrl.substring(start, end)
return get("$baseUrl/areader?id=$id&p=${pageUrl.substring(end+1)}", headers) return GET("$baseUrl/areader?id=$id&p=${pageUrl.substring(end+1)}", headers)
} }
override fun popularMangaParse(response: Response, page: MangasPage) { override fun popularMangaParse(response: Response, page: MangasPage) {
@ -216,9 +215,8 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex
} }
override fun login(username: String, password: String) = override fun login(username: String, password: String) =
network.request(get("$baseUrl/forums/index.php?app=core&module=global&section=login", headers)) network.request(GET("$baseUrl/forums/index.php?app=core&module=global&section=login", headers))
.map { it.body().string() } .flatMap { doLogin(it.body().string(), username, password) }
.flatMap { doLogin(it, username, password) }
.map { isAuthenticationSuccessful(it) } .map { isAuthenticationSuccessful(it) }
private fun doLogin(response: String, username: String, password: String): Observable<Response> { private fun doLogin(response: String, username: String, password: String): Observable<Response> {
@ -235,7 +233,7 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex
add("rememberMe", "1") add("rememberMe", "1")
}.build() }.build()
return network.request(post(url, headers, payload)) return network.request(POST(url, headers, payload))
} }
override fun isLoginRequired() = true override fun isLoginRequired() = true
@ -244,12 +242,7 @@ class Batoto(context: Context, override val id: Int) : ParsedOnlineSource(contex
response.priorResponse() != null && response.priorResponse().code() == 302 response.priorResponse() != null && response.priorResponse().code() == 302
override fun isLogged(): Boolean { override fun isLogged(): Boolean {
try { return network.cookies.get(URI(baseUrl)).any { it.name() == "pass_hash" }
return network.cookies.get(URI(baseUrl)).find { it.name() == "pass_hash" } != null
} catch (e: URISyntaxException) {
// Ignore
}
return false
} }
override fun fetchChapterList(manga: Manga): Observable<List<Chapter>> { override fun fetchChapterList(manga: Manga): Observable<List<Chapter>> {

View File

@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.data.source.online.english
import android.content.Context import android.content.Context
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.network.get import eu.kanade.tachiyomi.data.network.GET
import eu.kanade.tachiyomi.data.network.post import eu.kanade.tachiyomi.data.network.POST
import eu.kanade.tachiyomi.data.source.EN import eu.kanade.tachiyomi.data.source.EN
import eu.kanade.tachiyomi.data.source.Language import eu.kanade.tachiyomi.data.source.Language
import eu.kanade.tachiyomi.data.source.model.MangasPage import eu.kanade.tachiyomi.data.source.model.MangasPage
@ -54,7 +54,7 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
add("genres", "") add("genres", "")
}.build() }.build()
return post(page.url, headers, form) return POST(page.url, headers, form)
} }
override fun searchMangaInitialUrl(query: String) = "$baseUrl/AdvanceSearch" override fun searchMangaInitialUrl(query: String) = "$baseUrl/AdvanceSearch"
@ -95,7 +95,7 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
} ?: 0 } ?: 0
} }
override fun pageListRequest(chapter: Chapter) = post(baseUrl + chapter.url, headers) override fun pageListRequest(chapter: Chapter) = POST(baseUrl + chapter.url, headers)
override fun pageListParse(response: Response, pages: MutableList<Page>) { override fun pageListParse(response: Response, pages: MutableList<Page>) {
//language=RegExp //language=RegExp
@ -111,7 +111,7 @@ class Kissmanga(context: Context, override val id: Int) : ParsedOnlineSource(con
// Not used // Not used
override fun pageListParse(document: Document, pages: MutableList<Page>) {} override fun pageListParse(document: Document, pages: MutableList<Page>) {}
override fun imageUrlRequest(page: Page) = get(page.url) override fun imageUrlRequest(page: Page) = GET(page.url)
override fun imageUrlParse(document: Document) = "" override fun imageUrlParse(document: Document) = ""

View File

@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.data.source.online.english
import android.content.Context import android.content.Context
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.network.post import eu.kanade.tachiyomi.data.network.POST
import eu.kanade.tachiyomi.data.source.EN import eu.kanade.tachiyomi.data.source.EN
import eu.kanade.tachiyomi.data.source.Language import eu.kanade.tachiyomi.data.source.Language
import eu.kanade.tachiyomi.data.source.model.MangasPage import eu.kanade.tachiyomi.data.source.model.MangasPage
@ -47,7 +47,7 @@ class Readmangatoday(context: Context, override val id: Int) : ParsedOnlineSourc
var builder = okhttp3.FormBody.Builder() var builder = okhttp3.FormBody.Builder()
builder.add("query", query) builder.add("query", query)
return post(page.url, headers, builder.build()) return POST(page.url, headers, builder.build())
} }
override fun searchMangaSelector() = "div.content-list > div.style-list > div.box" override fun searchMangaSelector() = "div.content-list > div.style-list > div.box"

View File

@ -11,9 +11,10 @@ import android.support.v4.app.NotificationCompat
import eu.kanade.tachiyomi.App import eu.kanade.tachiyomi.App
import eu.kanade.tachiyomi.Constants import eu.kanade.tachiyomi.Constants
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.network.GET
import eu.kanade.tachiyomi.data.network.NetworkHelper import eu.kanade.tachiyomi.data.network.NetworkHelper
import eu.kanade.tachiyomi.data.network.ProgressListener import eu.kanade.tachiyomi.data.network.ProgressListener
import eu.kanade.tachiyomi.data.network.get import eu.kanade.tachiyomi.data.network.newCallWithProgress
import eu.kanade.tachiyomi.util.notificationManager import eu.kanade.tachiyomi.util.notificationManager
import eu.kanade.tachiyomi.util.saveTo import eu.kanade.tachiyomi.util.saveTo
import timber.log.Timber import timber.log.Timber
@ -100,12 +101,14 @@ class UpdateDownloader(private val context: Context) :
try { try {
// Make the request and download the file // Make the request and download the file
val response = network.requestBodyProgressBlocking(get(result.url), progressListener) val response = network.client.newCallWithProgress(GET(result.url), progressListener).execute()
if (response.isSuccessful) { if (response.isSuccessful) {
response.body().source().saveTo(apkFile) response.body().source().saveTo(apkFile)
// Set download successful // Set download successful
result.successful = true result.successful = true
} else {
response.close()
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, e.message) Timber.e(e, e.message)