diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/UrlImportableSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/UrlImportableSource.kt new file mode 100644 index 000000000..fce3cb19c --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/UrlImportableSource.kt @@ -0,0 +1,31 @@ +package eu.kanade.tachiyomi.source.online + +import android.net.Uri +import eu.kanade.tachiyomi.source.Source +import java.net.URI +import java.net.URISyntaxException + +interface UrlImportableSource : Source { + val matchingHosts: List + + fun matchesUri(uri: Uri): Boolean { + return (uri.host ?: "").toLowerCase() in matchingHosts + } + + // This method is allowed to block for IO if necessary + fun mapUrlToMangaUrl(uri: Uri): String? + + fun cleanMangaUrl(url: String): String { + return try { + val uri = URI(url) + var out = uri.path + if (uri.query != null) + out += "?" + uri.query + if (uri.fragment != null) + out += "#" + uri.fragment + out + } catch (e: URISyntaxException) { + url + } + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt index 58e98f858..dfa59a008 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt @@ -3,6 +3,10 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.net.Uri import com.elvishew.xlog.XLog +import com.github.salomonbrys.kotson.* +import com.google.gson.JsonArray +import com.google.gson.JsonObject +import com.google.gson.JsonParser import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault @@ -12,6 +16,7 @@ import eu.kanade.tachiyomi.network.asObservableWithAsyncStacktrace import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource +import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.util.asJsoup import exh.eh.EHentaiUpdateHelper import exh.metadata.EX_DATE_FORMAT @@ -46,7 +51,7 @@ import java.lang.RuntimeException // TODO Consider gallery updating when doing tabbed browsing class EHentai(override val id: Long, val exh: Boolean, - val context: Context) : HttpSource(), LewdSource { + val context: Context) : HttpSource(), LewdSource, UrlImportableSource { override val metaClass = EHentaiSearchMetadata::class val schema: String @@ -636,11 +641,67 @@ class EHentai(override val id: Long, class GalleryNotFoundException(cause: Throwable): RuntimeException("Gallery not found!", cause) + // === URL IMPORT STUFF + + override val matchingHosts: List = if(exh) listOf( + "exhentai.org" + ) else listOf( + "g.e-hentai.org", + "e-hentai.org" + ) + + override fun mapUrlToMangaUrl(uri: Uri): String? { + return when (uri.pathSegments.firstOrNull()) { + "g" -> { + //Is already gallery page, do nothing + uri.toString() + } + "s" -> { + //Is page, fetch gallery token and use that + getGalleryUrlFromPage(uri) + } + else -> null + } + } + + override fun cleanMangaUrl(url: String): String { + return EHentaiSearchMetadata.normalizeUrl(super.cleanMangaUrl(url)) + } + + private fun getGalleryUrlFromPage(uri: Uri): String { + val lastSplit = uri.pathSegments.last().split("-") + val pageNum = lastSplit.last() + val gallery = lastSplit.first() + val pageToken = uri.pathSegments.elementAt(1) + + val json = JsonObject() + json["method"] = "gtoken" + json["pagelist"] = JsonArray().apply { + add(JsonArray().apply { + add(gallery.toInt()) + add(pageToken) + add(pageNum.toInt()) + }) + } + + val outJson = JsonParser().parse(client.newCall(Request.Builder() + .url(EH_API_BASE) + .post(RequestBody.create(JSON, json.toString())) + .build()).execute().body()!!.string()).obj + + val obj = outJson["tokenlist"].array.first() + return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/" + } + + companion object { private const val QUERY_PREFIX = "?f_apply=Apply+Filter" private const val TR_SUFFIX = "TR" private const val REVERSE_PARAM = "TEH_REVERSE" + private const val EH_API_BASE = "https://api.e-hentai.org/api.php" + private val JSON = MediaType.parse("application/json; charset=utf-8")!! + private val FAVORITES_BORDER_HEX_COLORS = listOf( "000", "f00", diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt index e348d0550..486561a15 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.source.online.all +import android.net.Uri import android.os.Build import com.github.salomonbrys.kotson.array import com.github.salomonbrys.kotson.get @@ -12,7 +13,9 @@ import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource +import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.util.asJsoup +import exh.GalleryAddEvent import exh.HITOMI_SOURCE_ID import exh.hitomi.HitomiNozomi import exh.metadata.metadata.HitomiSearchMetadata @@ -36,7 +39,7 @@ import java.util.* /** * Man, I hate this source :( */ -class Hitomi : HttpSource(), LewdSource { +class Hitomi : HttpSource(), LewdSource, UrlImportableSource { private val prefs: PreferencesHelper by injectLazy() private val jsonParser by lazy { JsonParser() } @@ -390,6 +393,19 @@ class Hitomi : HttpSource(), LewdSource { .build() } + override val matchingHosts = listOf( + "hitomi.la" + ) + + override fun mapUrlToMangaUrl(uri: Uri): String? { + val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null + + if(lcFirstPathSegment != "galleries" && lcFirstPathSegment != "reader") + return null + + return "https://hitomi.la/galleries/${uri.pathSegments[1].substringBefore('.')}.html" + } + companion object { private val INDEX_VERSION_CACHE_TIME_MS = 1000 * 60 * 10 private val PAGE_SIZE = 25 diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt index 93c86ed5a..d500a0da6 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt @@ -13,7 +13,9 @@ import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource +import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.util.asJsoup +import exh.GalleryAddEvent import exh.NHENTAI_SOURCE_ID import exh.metadata.metadata.NHentaiSearchMetadata import exh.metadata.metadata.NHentaiSearchMetadata.Companion.TAG_TYPE_DEFAULT @@ -27,7 +29,7 @@ import rx.Observable * NHentai source */ -class NHentai(context: Context) : HttpSource(), LewdSource { +class NHentai(context: Context) : HttpSource(), LewdSource, UrlImportableSource { override val metaClass = NHentaiSearchMetadata::class override fun fetchPopularManga(page: Int): Observable { @@ -127,9 +129,6 @@ class NHentai(context: Context) : HttpSource(), LewdSource { + LewdSource, UrlImportableSource { /** * The class of the metadata used by this source */ @@ -306,6 +307,23 @@ class PervEden(override val id: Long, val pvLang: PervEdenLang) : ParsedHttpSour } } + override val matchingHosts = listOf("www.perveden.com") + + override fun matchesUri(uri: Uri): Boolean { + return super.matchesUri(uri) && uri.pathSegments.firstOrNull()?.toLowerCase() == when(pvLang) { + PervEdenLang.en -> "en-manga" + PervEdenLang.it -> "it-manga" + } + } + + override fun mapUrlToMangaUrl(uri: Uri): String? { + val newUri = Uri.parse("http://www.perveden.com/").buildUpon() + uri.pathSegments.take(3).forEach { + newUri.appendPath(it) + } + return newUri.toString() + } + companion object { val DATE_FORMAT = SimpleDateFormat("MMM d, yyyy", Locale.US).apply { timeZone = TimeZone.getTimeZone("GMT") diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HentaiCafe.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HentaiCafe.kt index e873e3164..051e743b4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HentaiCafe.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/HentaiCafe.kt @@ -1,11 +1,13 @@ package eu.kanade.tachiyomi.source.online.english +import android.net.Uri import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource +import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.util.asJsoup import exh.metadata.metadata.HentaiCafeSearchMetadata import exh.metadata.metadata.HentaiCafeSearchMetadata.Companion.TAG_TYPE_DEFAULT @@ -18,7 +20,7 @@ import org.jsoup.nodes.Document import rx.Observable class HentaiCafe(delegate: HttpSource) : DelegatedHttpSource(delegate), - LewdSource { + LewdSource, UrlImportableSource { /** * An ISO 639-1 compliant language code (two letters in lower case). */ @@ -88,4 +90,17 @@ class HentaiCafe(delegate: HttpSource) : DelegatedHttpSource(delegate), } ) }.toObservable() + + override val matchingHosts = listOf( + "hentai.cafe" + ) + + override fun mapUrlToMangaUrl(uri: Uri): String? { + val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null + + return if(lcFirstPathSegment == "manga") + "https://hentai.cafe/${uri.pathSegments[2]}" + else + "https://hentai.cafe/$lcFirstPathSegment" + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt index 4172ba7b5..369cf0f75 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/english/Tsumino.kt @@ -13,8 +13,10 @@ import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource +import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.toast +import exh.GalleryAddEvent import exh.TSUMINO_SOURCE_ID import exh.ui.captcha.ActionCompletionVerifier import exh.ui.captcha.BrowserActionActivity @@ -33,7 +35,10 @@ import uy.kohesive.injekt.injectLazy import java.text.SimpleDateFormat import java.util.* -class Tsumino(private val context: Context): ParsedHttpSource(), LewdSource, ActionCompletionVerifier { +class Tsumino(private val context: Context): ParsedHttpSource(), + LewdSource, + ActionCompletionVerifier, + UrlImportableSource { override val metaClass = TsuminoSearchMetadata::class private val preferences: PreferencesHelper by injectLazy() @@ -400,6 +405,19 @@ class Tsumino(private val context: Context): ParsedHttpSource(), LewdSource("Minimum rating", (0 .. 5).map { "$it stars" }.toTypedArray()) class ExcludeParodiesFilter : Filter.CheckBox("Exclude parodies") + override val matchingHosts = listOf( + "www.tsumino.com" + ) + + override fun mapUrlToMangaUrl(uri: Uri): String? { + val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null + + if(lcFirstPathSegment != "read" && lcFirstPathSegment != "book") + return null + + return "https://tsumino.com/Book/Info/${uri.pathSegments[2]}" + } + companion object { val jsonParser by lazy { JsonParser() diff --git a/app/src/main/java/exh/GalleryAdder.kt b/app/src/main/java/exh/GalleryAdder.kt index e7fc9309a..e8941e8c9 100755 --- a/app/src/main/java/exh/GalleryAdder.kt +++ b/app/src/main/java/exh/GalleryAdder.kt @@ -2,23 +2,13 @@ package exh import android.net.Uri import com.elvishew.xlog.XLog -import com.github.salomonbrys.kotson.* -import com.google.gson.JsonArray -import com.google.gson.JsonObject -import com.google.gson.JsonParser import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.source.online.all.EHentai import eu.kanade.tachiyomi.util.syncChaptersWithSource -import exh.metadata.metadata.EHentaiSearchMetadata -import okhttp3.MediaType -import okhttp3.Request -import okhttp3.RequestBody import uy.kohesive.injekt.injectLazy -import java.net.URI -import java.net.URISyntaxException class GalleryAdder { @@ -26,133 +16,55 @@ class GalleryAdder { private val sourceManager: SourceManager by injectLazy() - private val networkHelper: NetworkHelper by injectLazy() - - companion object { - const val EH_API_BASE = "https://api.e-hentai.org/api.php" - val JSON = MediaType.parse("application/json; charset=utf-8")!! - } - - fun getGalleryUrlFromPage(url: String): String { - val uri = Uri.parse(url) - val lastSplit = uri.pathSegments.last().split("-") - val pageNum = lastSplit.last() - val gallery = lastSplit.first() - val pageToken = uri.pathSegments.elementAt(1) - - val json = JsonObject() - json["method"] = "gtoken" - json["pagelist"] = JsonArray().apply { - add(JsonArray().apply { - add(gallery.toInt()) - add(pageToken) - add(pageNum.toInt()) - }) - } - - val outJson = JsonParser().parse(networkHelper.client.newCall(Request.Builder() - .url(EH_API_BASE) - .post(RequestBody.create(JSON, json.toString())) - .build()).execute().body()!!.string()).obj - - val obj = outJson["tokenlist"].array.first() - return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/" - } - fun addGallery(url: String, fav: Boolean = false, - forceSource: Long? = null, + forceSource: UrlImportableSource? = null, throttleFunc: () -> Unit = {}): GalleryAddEvent { XLog.d("Importing gallery (url: %s, fav: %s, forceSource: %s)...", url, fav, forceSource) try { - val urlObj = Uri.parse(url) - val lowercasePs = urlObj.pathSegments.map(String::toLowerCase) - val lcFirstPathSegment = lowercasePs[0] - val source = when (urlObj.host.toLowerCase()) { - "g.e-hentai.org", "e-hentai.org" -> EH_SOURCE_ID - "exhentai.org" -> EXH_SOURCE_ID - "nhentai.net" -> NHENTAI_SOURCE_ID - "www.perveden.com" -> { - when(lowercasePs[1]) { - "en-manga" -> PERV_EDEN_EN_SOURCE_ID - "it-manga" -> PERV_EDEN_IT_SOURCE_ID - else -> return GalleryAddEvent.Fail.UnknownType(url) - } + val uri = Uri.parse(url) + + // Find matching source + val source = if(forceSource != null) { + try { + if (forceSource.matchesUri(uri)) forceSource + else return GalleryAddEvent.Fail.UnknownType(url) + } catch(e: Exception) { + XLog.e("Source URI match check error!", e) + return GalleryAddEvent.Fail.UnknownType(url) } - "hentai.cafe" -> HENTAI_CAFE_SOURCE_ID - "www.tsumino.com" -> TSUMINO_SOURCE_ID - "hitomi.la" -> HITOMI_SOURCE_ID - else -> return GalleryAddEvent.Fail.UnknownType(url) + } else { + sourceManager.getVisibleCatalogueSources() + .filterIsInstance() + .find { + try { + it.matchesUri(uri) + } catch(e: Exception) { + XLog.e("Source URI match check error!", e) + false + } + } ?: return GalleryAddEvent.Fail.UnknownType(url) } - if(forceSource != null && source != forceSource) { - return GalleryAddEvent.Fail.UnknownType(url) - } + // Map URL to manga URL + val realUrl = try { + source.mapUrlToMangaUrl(uri) + } catch(e: Exception) { + XLog.e("Source URI map-to-manga error!", e) + null + } ?: return GalleryAddEvent.Fail.UnknownType(url) - val sourceObj = sourceManager.get(source) - ?: return GalleryAddEvent.Fail.Error(url, "Source not installed!") - - val realUrl = when(source) { - EH_SOURCE_ID, EXH_SOURCE_ID -> when (lcFirstPathSegment) { - "g" -> { - //Is already gallery page, do nothing - url - } - "s" -> { - //Is page, fetch gallery token and use that - getGalleryUrlFromPage(url) - } - else -> return GalleryAddEvent.Fail.UnknownType(url) - } - NHENTAI_SOURCE_ID -> { - if(lcFirstPathSegment != "g") - return GalleryAddEvent.Fail.UnknownType(url) - - "https://nhentai.net/g/${urlObj.pathSegments[1]}/" - } - PERV_EDEN_EN_SOURCE_ID, - PERV_EDEN_IT_SOURCE_ID -> { - val uri = Uri.parse("http://www.perveden.com/").buildUpon() - urlObj.pathSegments.take(3).forEach { - uri.appendPath(it) - } - uri.toString() - } - HENTAI_CAFE_SOURCE_ID -> { - if(lcFirstPathSegment == "manga") - "https://hentai.cafe/${urlObj.pathSegments[2]}" - - "https://hentai.cafe/$lcFirstPathSegment" - } - TSUMINO_SOURCE_ID -> { - if(lcFirstPathSegment != "read" && lcFirstPathSegment != "book") - return GalleryAddEvent.Fail.UnknownType(url) - - "https://tsumino.com/Book/Info/${urlObj.pathSegments[2]}" - } - HITOMI_SOURCE_ID -> { - if(lcFirstPathSegment != "galleries" && lcFirstPathSegment != "reader") - return GalleryAddEvent.Fail.UnknownType(url) - - "https://hitomi.la/galleries/${urlObj.pathSegments[1].substringBefore('.')}.html" - } - else -> return GalleryAddEvent.Fail.UnknownType(url) - } - - val cleanedUrl = when(source) { - EH_SOURCE_ID, EXH_SOURCE_ID -> EHentaiSearchMetadata.normalizeUrl(getUrlWithoutDomain(realUrl)) - NHENTAI_SOURCE_ID -> getUrlWithoutDomain(realUrl) - PERV_EDEN_EN_SOURCE_ID, - PERV_EDEN_IT_SOURCE_ID -> getUrlWithoutDomain(realUrl) - HENTAI_CAFE_SOURCE_ID -> getUrlWithoutDomain(realUrl) - TSUMINO_SOURCE_ID -> getUrlWithoutDomain(realUrl) - HITOMI_SOURCE_ID -> getUrlWithoutDomain(realUrl) - else -> return GalleryAddEvent.Fail.UnknownType(url) - } + // Clean URL + val cleanedUrl = try { + source.cleanMangaUrl(realUrl) + } catch(e: Exception) { + XLog.e("Source URI clean error!", e) + null + } ?: return GalleryAddEvent.Fail.UnknownType(url) //Use manga in DB if possible, otherwise, make a new manga - val manga = db.getManga(cleanedUrl, source).executeAsBlocking() - ?: Manga.create(source).apply { + val manga = db.getManga(cleanedUrl, source.id).executeAsBlocking() + ?: Manga.create(source.id).apply { this.url = cleanedUrl title = realUrl } @@ -166,7 +78,7 @@ class GalleryAdder { } // Fetch and copy details - val newManga = sourceObj.fetchMangaDetails(manga).toBlocking().first() + val newManga = source.fetchMangaDetails(manga).toBlocking().first() manga.copyFrom(newManga) manga.initialized = true @@ -176,13 +88,13 @@ class GalleryAdder { //Fetch and copy chapters try { - val chapterListObs = if(sourceObj is EHentai) { - sourceObj.fetchChapterList(manga, throttleFunc) + val chapterListObs = if(source is EHentai) { + source.fetchChapterList(manga, throttleFunc) } else { - sourceObj.fetchChapterList(manga) + source.fetchChapterList(manga) } chapterListObs.map { - syncChaptersWithSource(db, it, manga, sourceObj) + syncChaptersWithSource(db, it, manga, source) }.toBlocking().first() } catch (e: Exception) { XLog.w("Failed to update chapters for gallery: ${manga.title}!", e) @@ -201,20 +113,6 @@ class GalleryAdder { ((e.message ?: "Unknown error!") + " (Gallery: $url)").trim()) } } - - private fun getUrlWithoutDomain(orig: String): String { - return try { - val uri = URI(orig) - var out = uri.path - if (uri.query != null) - out += "?" + uri.query - if (uri.fragment != null) - out += "#" + uri.fragment - out - } catch (e: URISyntaxException) { - orig - } - } } sealed class GalleryAddEvent { @@ -224,9 +122,8 @@ sealed class GalleryAddEvent { class Success(override val galleryUrl: String, val manga: Manga): GalleryAddEvent() { + override val galleryTitle = manga.title override val logMessage = "Added gallery: $galleryTitle" - override val galleryTitle: String - get() = manga.title } sealed class Fail: GalleryAddEvent() { diff --git a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt index 1da85f857..7c4fa01ef 100644 --- a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt +++ b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt @@ -350,7 +350,7 @@ class FavoritesSyncHelper(val context: Context) { //Import using gallery adder val result = galleryAdder.addGallery("${exh.baseUrl}${it.getUrl()}", true, - EXH_SOURCE_ID, + exh, throttleManager::throttle) if(result is GalleryAddEvent.Fail) { diff --git a/app/src/main/java/exh/util/SearchOverride.kt b/app/src/main/java/exh/util/SearchOverride.kt index 48599be6e..0fefe81a9 100644 --- a/app/src/main/java/exh/util/SearchOverride.kt +++ b/app/src/main/java/exh/util/SearchOverride.kt @@ -1,7 +1,7 @@ package exh.util -import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.online.UrlImportableSource import exh.GalleryAddEvent import exh.GalleryAdder import rx.Observable @@ -13,11 +13,11 @@ private val galleryAdder by lazy { /** * A version of fetchSearchManga that supports URL importing */ -fun Source.urlImportFetchSearchManga(query: String, fail: () -> Observable) = +fun UrlImportableSource.urlImportFetchSearchManga(query: String, fail: () -> Observable) = when { query.startsWith("http://") || query.startsWith("https://") -> { Observable.fromCallable { - val res = galleryAdder.addGallery(query, false, id) + val res = galleryAdder.addGallery(query, false, this) MangasPage((if(res is GalleryAddEvent.Success) listOf(res.manga) else