diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a3663de98..65557c40d 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -189,10 +189,6 @@ android:exported="false" /> - - */, SearchMetadataQueries, SearchTagQueries, SearchTitleQueries, MergedQueries, SimilarQueries /* SY <-- */ { + MangaQueries, ChapterQueries, TrackQueries, CategoryQueries, MangaCategoryQueries, HistoryQueries /* SY --> */, SearchMetadataQueries, SearchTagQueries, SearchTitleQueries, MergedQueries /* SY <-- */ { private val configuration = SupportSQLiteOpenHelper.Configuration.builder(context) .name(DbOpenCallback.DATABASE_NAME) @@ -62,7 +59,6 @@ open class DatabaseHelper(context: Context) : .addTypeMapping(SearchTag::class.java, SearchTagTypeMapping()) .addTypeMapping(SearchTitle::class.java, SearchTitleTypeMapping()) .addTypeMapping(MergedMangaReference::class.java, MergedMangaTypeMapping()) - .addTypeMapping(MangaSimilar::class.java, SimilarTypeMapping()) // SY <-- .build() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/DbOpenCallback.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/DbOpenCallback.kt index e9b02ffa1..87bc214b9 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/DbOpenCallback.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/DbOpenCallback.kt @@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.data.database.tables.HistoryTable import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable import eu.kanade.tachiyomi.data.database.tables.MangaTable import eu.kanade.tachiyomi.data.database.tables.TrackTable -import exh.md.similar.sql.tables.SimilarTable import exh.merged.sql.tables.MergedTable import exh.metadata.sql.tables.SearchMetadataTable import exh.metadata.sql.tables.SearchTagTable @@ -25,7 +24,7 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) { /** * Version of the database. */ - const val DATABASE_VERSION = /* SY --> */ 6 /* SY <-- */ + const val DATABASE_VERSION = /* SY --> */ 7 /* SY <-- */ } override fun onCreate(db: SupportSQLiteDatabase) = with(db) { @@ -40,7 +39,6 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) { execSQL(SearchTagTable.createTableQuery) execSQL(SearchTitleTable.createTableQuery) execSQL(MergedTable.createTableQuery) - execSQL(SimilarTable.createTableQuery) // SY <-- // DB indexes @@ -57,7 +55,6 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) { execSQL(SearchTitleTable.createMangaIdIndexQuery) execSQL(SearchTitleTable.createTitleIndexQuery) execSQL(MergedTable.createIndexQuery) - execSQL(SimilarTable.createMangaIdIndexQuery) // SY <-- } @@ -74,13 +71,16 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) { db.execSQL(MergedTable.createTableQuery) db.execSQL(MergedTable.createIndexQuery) } - if (oldVersion < 5) { + /*if (oldVersion < 5) { db.execSQL(SimilarTable.createTableQuery) db.execSQL(SimilarTable.createMangaIdIndexQuery) - } + }*/ if (oldVersion < 6) { db.execSQL(MangaTable.addFilteredScanlators) } + if (oldVersion < 7) { + db.execSQL("DROP TABLE IF EXISTS manga_related") + } } override fun onConfigure(db: SupportSQLiteDatabase) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index 085d8f685..2c8b8dd81 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -26,7 +26,6 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.toast -import exh.md.similar.SimilarUpdateService import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy @@ -111,9 +110,6 @@ class NotificationReceiver : BroadcastReceiver() { "text/plain", intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1) ) - // SY --> - ACTION_CANCEL_SIMILAR_UPDATE -> cancelSimilarUpdate(context) - // SY <-- } } @@ -255,18 +251,6 @@ class NotificationReceiver : BroadcastReceiver() { } } - // SY --> - /** - * Method called when user wants to stop a similar manga update - * - * @param context context of application - */ - private fun cancelSimilarUpdate(context: Context) { - SimilarUpdateService.stop(context) - Handler().post { dismissNotification(context, Notifications.ID_SIMILAR_PROGRESS) } - } - // SY <-- - companion object { private const val NAME = "NotificationReceiver" @@ -299,11 +283,6 @@ class NotificationReceiver : BroadcastReceiver() { private const val EXTRA_CHAPTER_URL = "$ID.$NAME.EXTRA_CHAPTER_URL" private const val EXTRA_IS_LEGACY_BACKUP = "$ID.$NAME.EXTRA_IS_LEGACY_BACKUP" - // Sy --> - // Called to cancel similar manga update. - private const val ACTION_CANCEL_SIMILAR_UPDATE = "$ID.$NAME.CANCEL_SIMILAR_UPDATE" - // SY <-- - /** * Returns a [PendingIntent] that resumes the download of a chapter * @@ -572,20 +551,5 @@ class NotificationReceiver : BroadcastReceiver() { } return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } - - // SY --> - /** - * Returns [PendingIntent] that starts a service which stops the similar update - * - * @param context context of application - * @return [PendingIntent] - */ - internal fun cancelSimilarUpdatePendingBroadcast(context: Context): PendingIntent { - val intent = Intent(context, NotificationReceiver::class.java).apply { - action = ACTION_CANCEL_SIMILAR_UPDATE - } - return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) - } - // SY <-- } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt index b2d15c992..4a37b1243 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt @@ -74,15 +74,6 @@ object Notifications { const val CHANNEL_INCOGNITO_MODE = "incognito_mode_channel" const val ID_INCOGNITO_MODE = -701 - // SY --> - /** - * Notification channel and ids used for backup and restore. - */ - const val CHANNEL_SIMILAR = "similar_channel" - const val ID_SIMILAR_PROGRESS = -901 - const val ID_SIMILAR_COMPLETE = -902 - // SY <-- - private val deprecatedChannels = listOf( "downloader_channel", "backup_restore_complete_channel" @@ -174,14 +165,7 @@ object Notifications { CHANNEL_INCOGNITO_MODE, context.getString(R.string.pref_incognito_mode), NotificationManager.IMPORTANCE_LOW - ), - NotificationChannel( - CHANNEL_SIMILAR, - context.getString(R.string.similar_manga), - NotificationManager.IMPORTANCE_LOW - ).apply { - setShowBadge(false) - } + ) ).forEach(context.notificationManager::createNotificationChannel) // Delete old notification channels diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 8b2ee8cbe..1a8820679 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -327,12 +327,6 @@ object PreferenceKeys { const val mangaDexForceLatestCovers = "manga_dex_force_latest_covers" - const val mangadexSimilarEnabled = "pref_related_show_tab_key" - - const val mangadexSimilarUpdateInterval = "related_update_interval" - - const val mangadexSimilarOnlyOverWifi = "pref_simular_only_over_wifi_key" - const val mangadexSyncToLibraryIndexes = "pref_mangadex_sync_to_library_indexes" const val preferredMangaDexId = "preferred_mangaDex_id" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 978366e32..fc8c8cba5 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -446,16 +446,8 @@ class PreferencesHelper(val context: Context) { fun preferredMangaDexId() = flowPrefs.getString(Keys.preferredMangaDexId, "0") - fun mangadexSimilarEnabled() = flowPrefs.getBoolean(Keys.mangadexSimilarEnabled, false) - - fun shownMangaDexSimilarAskDialog() = flowPrefs.getBoolean("shown_similar_ask_dialog", false) - - fun mangadexSimilarOnlyOverWifi() = flowPrefs.getBoolean(Keys.mangadexSimilarOnlyOverWifi, true) - fun mangadexSyncToLibraryIndexes() = flowPrefs.getStringSet(Keys.mangadexSyncToLibraryIndexes, emptySet()) - fun mangadexSimilarUpdateInterval() = flowPrefs.getInt(Keys.mangadexSimilarUpdateInterval, 2) - fun dataSaver() = flowPrefs.getBoolean(Keys.dataSaver, false) fun ignoreJpeg() = flowPrefs.getBoolean(Keys.ignoreJpeg, false) diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt index 2d3ab636d..da5f25b7a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context -import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.track.TrackManager @@ -242,8 +241,8 @@ class MangaDex(delegate: HttpSource, val context: Context) : return MangaHandler(baseHttpClient, headers, mdLang.lang).fetchRandomMangaId() } - suspend fun fetchMangaSimilar(manga: Manga): MangasPage { - return SimilarHandler(preferences, useLowQualityThumbnail()).fetchSimilar(manga) + suspend fun getMangaSimilar(manga: MangaInfo): MangasPage { + return SimilarHandler(baseHttpClient, mdLang.lang, preferences, useLowQualityThumbnail()).getSimilar(manga) } /*private fun importIdToMdId(query: String, fail: () -> Observable): Observable = diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt index 71a567623..acbde9fc5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt @@ -35,7 +35,6 @@ import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LoginSource -import eu.kanade.tachiyomi.source.online.all.MangaDex import eu.kanade.tachiyomi.ui.base.controller.FabController import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction @@ -57,7 +56,6 @@ import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.EmptyView import exh.log.xLogW -import exh.md.similar.ui.EnableMangaDexSimilarDialogController import exh.savedsearches.EXHSavedSearch import exh.source.getMainSource import exh.source.isEhBasedSource @@ -172,11 +170,6 @@ open class BrowseSourceController(bundle: Bundle) : // SY --> val mainSource = presenter.source.getMainSource() - if (mainSource is MangaDex && !preferences.mangadexSimilarEnabled().get() && !preferences.shownMangaDexSimilarAskDialog().get()) { - EnableMangaDexSimilarDialogController().showDialog(router) - preferences.shownMangaDexSimilarAskDialog().set(true) - } - if (mainSource is LoginSource && mainSource.requiresLogin && !mainSource.isLogged()) { val dialog = MangadexLoginDialog(mainSource) dialog.showDialog(router) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 419e68407..7cd75fc61 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -102,7 +102,7 @@ import eu.kanade.tachiyomi.util.view.getCoordinates import eu.kanade.tachiyomi.util.view.shrinkOnScroll import eu.kanade.tachiyomi.util.view.snack import exh.log.xLogD -import exh.md.similar.ui.MangaDexSimilarController +import exh.md.similar.MangaDexSimilarController import exh.metadata.metadata.base.FlatMetadata import exh.recs.RecommendsController import exh.source.MERGED_SOURCE_ID @@ -767,7 +767,7 @@ class MangaController : // AZ --> fun openRecommends() { val source = presenter.source.getMainSource() - if (source is MangaDex && preferences.mangadexSimilarEnabled().get()) { + if (source is MangaDex) { MaterialDialog(activity!!) .title(R.string.az_recommends) .listItemsSingleChoice( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMangaDexController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMangaDexController.kt index dc771e695..a5cbc9758 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMangaDexController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMangaDexController.kt @@ -6,27 +6,16 @@ import com.afollestad.materialdialogs.list.listItemsMultiChoice import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.preference.PreferenceKeys -import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.source.Source -import eu.kanade.tachiyomi.ui.base.controller.openInBrowser -import eu.kanade.tachiyomi.util.preference.defaultValue -import eu.kanade.tachiyomi.util.preference.entriesRes -import eu.kanade.tachiyomi.util.preference.intListPreference import eu.kanade.tachiyomi.util.preference.listPreference import eu.kanade.tachiyomi.util.preference.onClick import eu.kanade.tachiyomi.util.preference.preference -import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.summaryRes -import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.titleRes -import eu.kanade.tachiyomi.util.system.toast -import exh.md.similar.SimilarUpdateJob import exh.md.utils.MdUtil import exh.widget.preference.MangaDexLoginPreference import exh.widget.preference.MangadexLoginDialog import exh.widget.preference.MangadexLogoutDialog -import kotlinx.coroutines.flow.drop -import kotlinx.coroutines.flow.launchIn class SettingsMangaDexController : SettingsController(), @@ -108,76 +97,6 @@ class SettingsMangaDexController : ) } } - - preferenceCategory { - titleRes = R.string.similar_settings - - preference { - key = "pref_similar_screen" - summaryRes = R.string.similar_screen_summary_message - isIconSpaceReserved = true - } - - switchPreference { - key = PreferenceKeys.mangadexSimilarEnabled - titleRes = R.string.similar_screen - defaultValue = false - onClick { - SimilarUpdateJob.setupTask(context) - } - } - - switchPreference { - key = PreferenceKeys.mangadexSimilarOnlyOverWifi - titleRes = R.string.pref_download_only_over_wifi - defaultValue = true - onClick { - SimilarUpdateJob.setupTask(context, true) - } - } - - preference { - key = "pref_similar_manually_update" - titleRes = R.string.similar_manually_update - summaryRes = R.string.similar_manually_update_message - onClick { - SimilarUpdateJob.doWorkNow(context) - context.toast(R.string.similar_manually_toast) - } - } - - intListPreference { - key = PreferenceKeys.mangadexSimilarUpdateInterval - titleRes = R.string.similar_update_fequency - entriesRes = arrayOf( - R.string.update_never, - R.string.update_24hour, - R.string.update_48hour, - R.string.update_weekly, - R.string.update_monthly - ) - entryValues = arrayOf("0", "1", "2", "7", "30") - defaultValue = "2" - - preferences.mangadexSimilarUpdateInterval() - .asImmediateFlow { - SimilarUpdateJob.setupTask(context, true) - } - .drop(1) - .launchIn(viewScope) - } - - preference { - key = "similar_credits" - titleRes = R.string.similar_credit - val url = "https://github.com/goldbattle/MangadexRecomendations" - summary = context.getString(R.string.similar_credit_message, url) - onClick { - openInBrowser(url) - } - isIconSpaceReserved = true - } - } } override fun siteLoginDialogClosed(source: Source) { diff --git a/app/src/main/java/exh/md/handlers/SimilarHandler.kt b/app/src/main/java/exh/md/handlers/SimilarHandler.kt index 35986a711..b89121530 100644 --- a/app/src/main/java/exh/md/handlers/SimilarHandler.kt +++ b/app/src/main/java/exh/md/handlers/SimilarHandler.kt @@ -1,36 +1,40 @@ package exh.md.handlers -import eu.kanade.tachiyomi.data.database.DatabaseHelper -import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.await +import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.SManga -import exh.md.similar.sql.models.MangaSimilarImpl +import exh.md.handlers.serializers.SimilarMangaResponse import exh.md.utils.MdUtil -import exh.util.executeOnIO -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get +import okhttp3.CacheControl +import okhttp3.Headers +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import tachiyomi.source.model.MangaInfo -class SimilarHandler(val preferences: PreferencesHelper, private val useLowQualityCovers: Boolean) { +class SimilarHandler(val client: OkHttpClient, val lang: String, val preferences: PreferencesHelper, private val useLowQualityCovers: Boolean) { - /** - * fetch our similar mangas - */ - suspend fun fetchSimilar(manga: Manga): MangasPage { - // Parse the Mangadex id from the URL - val mangaId = MdUtil.getMangaId(manga.url).toLong() - val similarMangaDb = Injekt.get().getSimilar(mangaId).executeOnIO() - return if (similarMangaDb != null) { - val similarMangaTitles = similarMangaDb.matched_titles.split(MangaSimilarImpl.DELIMITER) - val similarMangaIds = similarMangaDb.matched_ids.split(MangaSimilarImpl.DELIMITER) - val similarMangas = similarMangaIds.mapIndexed { index, similarId -> - SManga.create().apply { - title = similarMangaTitles[index] - url = "/manga/$similarId/" - thumbnail_url = MdUtil.formThumbUrl(url, useLowQualityCovers) - } + suspend fun getSimilar(manga: MangaInfo): MangasPage { + val response = client.newCall(similarMangaRequest(manga)).await() + return similarMangaParse(response) + } + + private fun similarMangaRequest(manga: MangaInfo): Request { + val tempUrl = MdUtil.similarBaseApi + MdUtil.getMangaId(manga.key) + ".json" + return GET(tempUrl, Headers.Builder().build(), CacheControl.FORCE_NETWORK) + } + + private fun similarMangaParse(response: Response): MangasPage { + val mangaList = response.parseAs().matches.map { + SManga.create().apply { + url = "/manga/" + it.id + title = MdUtil.cleanString(it.title[lang] ?: it.title["en"]!!) + thumbnail_url = "https://coverapi.orell.dev/api/v1/mdaltimage/manga/${it.id}/cover" } - MangasPage(similarMangas, false) - } else MangasPage(mutableListOf(), false) + } + return MangasPage(mangaList, false) } } diff --git a/app/src/main/java/exh/md/handlers/serializers/SimilarSerializer.kt b/app/src/main/java/exh/md/handlers/serializers/SimilarSerializer.kt new file mode 100644 index 000000000..0ff07c07b --- /dev/null +++ b/app/src/main/java/exh/md/handlers/serializers/SimilarSerializer.kt @@ -0,0 +1,20 @@ +package exh.md.handlers.serializers + +import kotlinx.serialization.Serializable + +@Serializable +data class SimilarMangaResponse( + val id: String, + val title: Map, + val contentRating: String, + val matches: List, + val updatedAt: String +) + +@Serializable +data class Matches( + val id: String, + val title: Map, + val contentRating: String, + val score: Double +) diff --git a/app/src/main/java/exh/md/similar/ui/MangaDexSimilarController.kt b/app/src/main/java/exh/md/similar/MangaDexSimilarController.kt similarity index 98% rename from app/src/main/java/exh/md/similar/ui/MangaDexSimilarController.kt rename to app/src/main/java/exh/md/similar/MangaDexSimilarController.kt index 92bb81c96..2dc7d8901 100644 --- a/app/src/main/java/exh/md/similar/ui/MangaDexSimilarController.kt +++ b/app/src/main/java/exh/md/similar/MangaDexSimilarController.kt @@ -1,4 +1,4 @@ -package exh.md.similar.ui +package exh.md.similar import android.os.Bundle import android.view.Menu diff --git a/app/src/main/java/exh/md/similar/ui/MangaDexSimilarPager.kt b/app/src/main/java/exh/md/similar/MangaDexSimilarPager.kt similarity index 85% rename from app/src/main/java/exh/md/similar/ui/MangaDexSimilarPager.kt rename to app/src/main/java/exh/md/similar/MangaDexSimilarPager.kt index 372c151e3..dfe63e63c 100644 --- a/app/src/main/java/exh/md/similar/ui/MangaDexSimilarPager.kt +++ b/app/src/main/java/exh/md/similar/MangaDexSimilarPager.kt @@ -1,6 +1,7 @@ -package exh.md.similar.ui +package exh.md.similar import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.database.models.toMangaInfo import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.online.all.MangaDex import eu.kanade.tachiyomi.ui.browse.source.browse.NoResultsException @@ -16,7 +17,7 @@ import rx.schedulers.Schedulers class MangaDexSimilarPager(val manga: Manga, val source: MangaDex) : Pager() { override fun requestNext(): Observable { - return runAsObservable({ source.fetchMangaSimilar(manga) }) + return runAsObservable({ source.getMangaSimilar(manga.toMangaInfo()) }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnNext { diff --git a/app/src/main/java/exh/md/similar/ui/MangaDexSimilarPresenter.kt b/app/src/main/java/exh/md/similar/MangaDexSimilarPresenter.kt similarity index 97% rename from app/src/main/java/exh/md/similar/ui/MangaDexSimilarPresenter.kt rename to app/src/main/java/exh/md/similar/MangaDexSimilarPresenter.kt index 17a7e978a..5b685d1fc 100644 --- a/app/src/main/java/exh/md/similar/ui/MangaDexSimilarPresenter.kt +++ b/app/src/main/java/exh/md/similar/MangaDexSimilarPresenter.kt @@ -1,4 +1,4 @@ -package exh.md.similar.ui +package exh.md.similar import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Manga diff --git a/app/src/main/java/exh/md/similar/SimilarUpdateJob.kt b/app/src/main/java/exh/md/similar/SimilarUpdateJob.kt deleted file mode 100644 index 38b9983b6..000000000 --- a/app/src/main/java/exh/md/similar/SimilarUpdateJob.kt +++ /dev/null @@ -1,74 +0,0 @@ -package exh.md.similar - -import android.content.Context -import androidx.work.Constraints -import androidx.work.ExistingPeriodicWorkPolicy -import androidx.work.NetworkType -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.PeriodicWorkRequestBuilder -import androidx.work.WorkManager -import androidx.work.Worker -import androidx.work.WorkerParameters -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import java.util.concurrent.TimeUnit - -class SimilarUpdateJob(private val context: Context, workerParams: WorkerParameters) : - Worker(context, workerParams) { - - override fun doWork(): Result { - SimilarUpdateService.start(context) - return Result.success() - } - - companion object { - const val TAG = "RelatedUpdate" - - fun setupTask(context: Context, skipInitial: Boolean = false) { - val preferences = Injekt.get() - val enabled = preferences.mangadexSimilarEnabled().get() - val interval = preferences.mangadexSimilarUpdateInterval().get() - if (enabled) { - // We are enabled, so construct the constraints - val wifiRestriction = if (preferences.mangadexSimilarOnlyOverWifi().get()) { - NetworkType.UNMETERED - } else { - NetworkType.CONNECTED - } - val constraints = Constraints.Builder() - .setRequiredNetworkType(wifiRestriction) - .build() - - // If we are not skipping the initial then run it right now - // Note that we won't run it if the constraints are not satisfied - if (!skipInitial) { - WorkManager.getInstance(context).enqueue(OneTimeWorkRequestBuilder().setConstraints(constraints).build()) - } - - // Finally build the periodic request - val request = PeriodicWorkRequestBuilder( - interval.toLong(), - TimeUnit.DAYS, - 1, - TimeUnit.HOURS - ) - .addTag(TAG) - .setConstraints(constraints) - .build() - - if (interval > 0) { - WorkManager.getInstance(context).enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.REPLACE, request) - } else { - WorkManager.getInstance(context).cancelAllWorkByTag(TAG) - } - } else { - WorkManager.getInstance(context).cancelAllWorkByTag(TAG) - } - } - - fun doWorkNow(context: Context) { - WorkManager.getInstance(context).enqueue(OneTimeWorkRequestBuilder().build()) - } - } -} diff --git a/app/src/main/java/exh/md/similar/SimilarUpdateService.kt b/app/src/main/java/exh/md/similar/SimilarUpdateService.kt deleted file mode 100644 index 619c9f254..000000000 --- a/app/src/main/java/exh/md/similar/SimilarUpdateService.kt +++ /dev/null @@ -1,351 +0,0 @@ -package exh.md.similar - -import android.app.Service -import android.content.Context -import android.content.Intent -import android.graphics.BitmapFactory -import android.os.IBinder -import android.os.PowerManager -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import androidx.core.content.ContextCompat -import androidx.core.text.isDigitsOnly -import com.squareup.moshi.JsonReader -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.DatabaseHelper -import eu.kanade.tachiyomi.data.notification.NotificationReceiver -import eu.kanade.tachiyomi.data.notification.Notifications -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.NetworkHelper -import eu.kanade.tachiyomi.network.await -import eu.kanade.tachiyomi.util.lang.withIOContext -import eu.kanade.tachiyomi.util.system.acquireWakeLock -import eu.kanade.tachiyomi.util.system.isServiceRunning -import eu.kanade.tachiyomi.util.system.notificationManager -import exh.log.xLogE -import exh.md.similar.sql.models.MangaSimilarImpl -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.cancel -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import okio.buffer -import okio.sink -import okio.source -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import java.io.File - -class SimilarUpdateService( - val db: DatabaseHelper = Injekt.get() -) : Service() { - - private val client by lazy { - Injekt.get().client.newBuilder() - // unzip interceptor which will add the correct headers - .addNetworkInterceptor { chain -> - val originalResponse = chain.proceed(chain.request()) - originalResponse.newBuilder() - .header("Content-Encoding", "gzip") - .header("Content-Type", "application/json") - .build() - } - .build() - } - - /** - * Wake lock that will be held until the service is destroyed. - */ - private lateinit var wakeLock: PowerManager.WakeLock - - private val similarServiceScope = CoroutineScope(Dispatchers.IO + Job()) - - /** - * Subscription where the update is done. - */ - private var job: Job? = null - - /** - * Pending intent of action that cancels the library update - */ - private val cancelIntent by lazy { - NotificationReceiver.cancelSimilarUpdatePendingBroadcast(this) - } - - private val progressNotification by lazy { - NotificationCompat.Builder(this, Notifications.CHANNEL_SIMILAR) - .setLargeIcon(BitmapFactory.decodeResource(this.resources, R.mipmap.ic_launcher)) - .setSmallIcon(R.drawable.ic_tachi) - .setOngoing(true) - .setContentTitle(getString(R.string.similar_loading_progress_start)) - .setAutoCancel(true) - .addAction( - R.drawable.ic_close_24dp, - getString(android.R.string.cancel), - cancelIntent - ) - } - - /** - * Method called when the service is created. It injects dagger dependencies and acquire - * the wake lock. - */ - override fun onCreate() { - super.onCreate() - wakeLock = acquireWakeLock("SimilarUpdateService") - startForeground(Notifications.ID_SIMILAR_PROGRESS, progressNotification.build()) - } - - override fun stopService(name: Intent?): Boolean { - destroyJob() - return super.stopService(name) - } - - override fun onDestroy() { - destroyJob() - super.onDestroy() - } - - private fun destroyJob() { - job?.cancel() - if (similarServiceScope.isActive) similarServiceScope.cancel() - if (wakeLock.isHeld) { - wakeLock.release() - } - } - - /** - * This method needs to be implemented, but it's not used/needed. - */ - override fun onBind(intent: Intent): IBinder? = null - - /** - * Method called when the service receives an intent. - * - * @param intent the start intent from. - * @param flags the flags of the command. - * @param startId the start id of this command. - * @return the start value of the command. - */ - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (intent == null) return START_NOT_STICKY - - // Unsubscribe from any previous subscription if needed. - job?.cancel() - val handler = CoroutineExceptionHandler { _, exception -> - xLogE("Similar manga update error", exception) - stopSelf(startId) - showResultNotification(true) - cancelProgressNotification() - } - job = similarServiceScope.launch(handler) { - updateSimilar() - } - job?.invokeOnCompletion { stopSelf(startId) } - - return START_REDELIVER_INTENT - } - - /** - * Method that updates the similar database for manga - */ - private suspend fun updateSimilar() = withIOContext { - val response = client - .newCall(GET(similarUrl)) - .await() - if (!response.isSuccessful) { - throw Exception("Error trying to download similar file") - } - val destinationFile = File(filesDir, "neko-similar.json") - val buffer = withIOContext { destinationFile.sink().buffer() } - - // write json to file - response.body?.byteStream()?.source()?.use { input -> - buffer.use { output -> - output.writeAll(input) - } - } - - val listSimilar = getSimilar(destinationFile) - - // Delete the old similar table - db.deleteAllSimilar().executeAsBlocking() - - val totalManga = listSimilar.size - - // Loop through each and insert into the database - - val dataToInsert = listSimilar.mapIndexed { index, similarFromJson -> - showProgressNotification(index, totalManga) - - if (similarFromJson.similarIds.size != similarFromJson.similarTitles.size) { - return@mapIndexed null - } - - MangaSimilarImpl().apply { - id = index.toLong() - manga_id = similarFromJson.id.toLong() - matched_ids = similarFromJson.similarIds.joinToString(MangaSimilarImpl.DELIMITER) - matched_titles = similarFromJson.similarTitles.joinToString(MangaSimilarImpl.DELIMITER) - } - }.filterNotNull() - - showProgressNotification(dataToInsert.size, totalManga) - - if (dataToInsert.isNotEmpty()) { - db.insertSimilar(dataToInsert).executeAsBlocking() - } - destinationFile.delete() - showResultNotification(!this.isActive) - cancelProgressNotification() - } - - private fun getSimilar(destinationFile: File): List { - val reader = JsonReader.of(destinationFile.source().buffer()) - - var processingManga = false - var processingTitles = false - var mangaId: String? = null - var similarIds = mutableListOf() - var similarTitles = mutableListOf() - val similars = mutableListOf() - - while (reader.peek() != JsonReader.Token.END_DOCUMENT) { - when (reader.peek()) { - JsonReader.Token.BEGIN_OBJECT -> { - reader.beginObject() - } - JsonReader.Token.NAME -> { - val name = reader.nextName() - if (!processingManga && name.isDigitsOnly()) { - processingManga = true - // similar add id - mangaId = name - } else if (name == "m_titles") { - processingTitles = true - } - } - JsonReader.Token.BEGIN_ARRAY -> { - reader.beginArray() - } - JsonReader.Token.END_ARRAY -> { - reader.endArray() - if (processingTitles) { - processingManga = false - processingTitles = false - similars.add(SimilarFromJson(mangaId!!, similarIds.toList(), similarTitles.toList())) - mangaId = null - similarIds = mutableListOf() - similarTitles = mutableListOf() - } - } - JsonReader.Token.NUMBER -> { - similarIds.add(reader.nextInt().toString()) - } - JsonReader.Token.STRING -> { - if (processingTitles) { - similarTitles.add(reader.nextString()) - } - } - JsonReader.Token.END_OBJECT -> { - reader.endObject() - } - else -> Unit - } - } - - return similars - } - - data class SimilarFromJson(val id: String, val similarIds: List, val similarTitles: List) - - /** - * Shows the notification containing the currently updating manga and the progress. - * - * @param current the current progress. - * @param total the total progress. - */ - private fun showProgressNotification(current: Int, total: Int) { - notificationManager.notify( - Notifications.ID_SIMILAR_PROGRESS, - progressNotification - .setContentTitle( - getString( - R.string.similar_loading_percent, - current, - total - ) - ) - .setProgress(total, current, false) - .build() - ) - } - - /** - * Shows the notification containing the result of the update done by the service. - * - * @param error if the result was a error. - */ - private fun showResultNotification(error: Boolean = false) { - val title = if (error) { - getString(R.string.similar_loading_complete_error) - } else { - getString( - R.string.similar_loading_complete - ) - } - - val result = NotificationCompat.Builder(this, Notifications.CHANNEL_SIMILAR) - .setContentTitle(title) - .setLargeIcon(BitmapFactory.decodeResource(this.resources, R.mipmap.ic_launcher)) - .setSmallIcon(R.drawable.ic_tachi) - .setAutoCancel(true) - NotificationManagerCompat.from(this) - .notify(Notifications.ID_SIMILAR_COMPLETE, result.build()) - } - - /** - * Cancels the progress notification. - */ - private fun cancelProgressNotification() { - notificationManager.cancel(Notifications.ID_SIMILAR_PROGRESS) - } - - companion object { - private const val similarUrl = "https://raw.githubusercontent.com/goldbattle/MangadexRecomendations/master/output/mangas_compressed.json.gz" - - /** - * Returns the status of the service. - * - * @param context the application context. - * @return true if the service is running, false otherwise. - */ - fun isRunning(context: Context): Boolean { - return context.isServiceRunning(SimilarUpdateService::class.java) - } - - /** - * Starts the service. It will be started only if there isn't another instance already - * running. - * - * @param context the application context. - */ - fun start(context: Context) { - if (!isRunning(context)) { - val intent = Intent(context, SimilarUpdateService::class.java) - ContextCompat.startForegroundService(context, intent) - } - } - - /** - * Stops the service. - * - * @param context the application context. - */ - fun stop(context: Context) { - context.stopService(Intent(context, SimilarUpdateService::class.java)) - } - } -} diff --git a/app/src/main/java/exh/md/similar/sql/mappers/SimilarTypeMapping.kt b/app/src/main/java/exh/md/similar/sql/mappers/SimilarTypeMapping.kt deleted file mode 100644 index 6bebf299f..000000000 --- a/app/src/main/java/exh/md/similar/sql/mappers/SimilarTypeMapping.kt +++ /dev/null @@ -1,63 +0,0 @@ -package exh.md.similar.sql.mappers - -import android.database.Cursor -import androidx.core.content.contentValuesOf -import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping -import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver -import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver -import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.InsertQuery -import com.pushtorefresh.storio.sqlite.queries.UpdateQuery -import exh.md.similar.sql.models.MangaSimilar -import exh.md.similar.sql.models.MangaSimilarImpl -import exh.md.similar.sql.tables.SimilarTable.COL_ID -import exh.md.similar.sql.tables.SimilarTable.COL_MANGA_ID -import exh.md.similar.sql.tables.SimilarTable.COL_MANGA_SIMILAR_MATCHED_IDS -import exh.md.similar.sql.tables.SimilarTable.COL_MANGA_SIMILAR_MATCHED_TITLES -import exh.md.similar.sql.tables.SimilarTable.TABLE - -class SimilarTypeMapping : SQLiteTypeMapping( - SimilarPutResolver(), - SimilarGetResolver(), - SimilarDeleteResolver() -) - -class SimilarPutResolver : DefaultPutResolver() { - - override fun mapToInsertQuery(obj: MangaSimilar) = InsertQuery.builder() - .table(TABLE) - .build() - - override fun mapToUpdateQuery(obj: MangaSimilar) = UpdateQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() - - override fun mapToContentValues(obj: MangaSimilar) = contentValuesOf( - COL_ID to obj.id, - COL_MANGA_ID to obj.manga_id, - COL_MANGA_SIMILAR_MATCHED_IDS to obj.matched_ids, - COL_MANGA_SIMILAR_MATCHED_TITLES to obj.matched_titles - ) -} - -class SimilarGetResolver : DefaultGetResolver() { - - override fun mapFromCursor(cursor: Cursor): MangaSimilar = MangaSimilarImpl().apply { - id = cursor.getLong(cursor.getColumnIndex(COL_ID)) - manga_id = cursor.getLong(cursor.getColumnIndex(COL_MANGA_ID)) - matched_ids = cursor.getString(cursor.getColumnIndex(COL_MANGA_SIMILAR_MATCHED_IDS)) - matched_titles = cursor.getString(cursor.getColumnIndex(COL_MANGA_SIMILAR_MATCHED_TITLES)) - } -} - -class SimilarDeleteResolver : DefaultDeleteResolver() { - - override fun mapToDeleteQuery(obj: MangaSimilar) = DeleteQuery.builder() - .table(TABLE) - .where("$COL_ID = ?") - .whereArgs(obj.id) - .build() -} diff --git a/app/src/main/java/exh/md/similar/sql/models/MangaSimilar.kt b/app/src/main/java/exh/md/similar/sql/models/MangaSimilar.kt deleted file mode 100644 index 03d050bc9..000000000 --- a/app/src/main/java/exh/md/similar/sql/models/MangaSimilar.kt +++ /dev/null @@ -1,31 +0,0 @@ -package exh.md.similar.sql.models - -import java.io.Serializable - -/** - * Object containing the history statistics of a chapter - */ -interface MangaSimilar : Serializable { - - /** - * Id of this similar manga object. - */ - var id: Long? - - /** - * Id of matching manga - */ - var manga_id: Long? - - /** - * JSONArray.toString() list of ids for this manga - * Example: [3467, 5907, 21052, 2141, 6139, 5602, 3999] - */ - var matched_ids: String - - /** - * JSONArray.toString() list of titles for this manga - * Example: [Title1, Title2, ..., Title10] - */ - var matched_titles: String -} diff --git a/app/src/main/java/exh/md/similar/sql/models/MangaSimilarImpl.kt b/app/src/main/java/exh/md/similar/sql/models/MangaSimilarImpl.kt deleted file mode 100644 index 07297b4c1..000000000 --- a/app/src/main/java/exh/md/similar/sql/models/MangaSimilarImpl.kt +++ /dev/null @@ -1,32 +0,0 @@ -package exh.md.similar.sql.models - -class MangaSimilarImpl : MangaSimilar { - - override var id: Long? = null - - override var manga_id: Long? = null - - override lateinit var matched_ids: String - - override lateinit var matched_titles: String - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || javaClass != other.javaClass) return false - - other as MangaSimilar - - if (id != other.id) return false - if (manga_id != other.manga_id) return false - if (matched_ids != other.matched_ids) return false - return matched_titles != other.matched_titles - } - - override fun hashCode(): Int { - return id.hashCode() + manga_id.hashCode() - } - - companion object { - const val DELIMITER = "|*|" - } -} diff --git a/app/src/main/java/exh/md/similar/sql/queries/SimilarQueries.kt b/app/src/main/java/exh/md/similar/sql/queries/SimilarQueries.kt deleted file mode 100644 index ad430078c..000000000 --- a/app/src/main/java/exh/md/similar/sql/queries/SimilarQueries.kt +++ /dev/null @@ -1,42 +0,0 @@ -package exh.md.similar.sql.queries - -import com.pushtorefresh.storio.sqlite.queries.DeleteQuery -import com.pushtorefresh.storio.sqlite.queries.Query -import eu.kanade.tachiyomi.data.database.DbProvider -import exh.md.similar.sql.models.MangaSimilar -import exh.md.similar.sql.tables.SimilarTable - -interface SimilarQueries : DbProvider { - - fun getAllSimilar() = db.get() - .listOfObjects(MangaSimilar::class.java) - .withQuery( - Query.builder() - .table(SimilarTable.TABLE) - .build() - ) - .prepare() - - fun getSimilar(manga_id: Long) = db.get() - .`object`(MangaSimilar::class.java) - .withQuery( - Query.builder() - .table(SimilarTable.TABLE) - .where("${SimilarTable.COL_MANGA_ID} = ?") - .whereArgs(manga_id) - .build() - ) - .prepare() - - fun insertSimilar(similar: MangaSimilar) = db.put().`object`(similar).prepare() - - fun insertSimilar(similarList: List) = db.put().objects(similarList).prepare() - - fun deleteAllSimilar() = db.delete() - .byQuery( - DeleteQuery.builder() - .table(SimilarTable.TABLE) - .build() - ) - .prepare() -} diff --git a/app/src/main/java/exh/md/similar/sql/tables/SimilarTable.kt b/app/src/main/java/exh/md/similar/sql/tables/SimilarTable.kt deleted file mode 100644 index 937f8f1df..000000000 --- a/app/src/main/java/exh/md/similar/sql/tables/SimilarTable.kt +++ /dev/null @@ -1,27 +0,0 @@ -package exh.md.similar.sql.tables - -object SimilarTable { - - const val TABLE = "manga_related" - - const val COL_ID = "_id" - - const val COL_MANGA_ID = "manga_id" - - const val COL_MANGA_SIMILAR_MATCHED_IDS = "matched_ids" - - const val COL_MANGA_SIMILAR_MATCHED_TITLES = "matched_titles" - - val createTableQuery: String - get() = - """CREATE TABLE $TABLE( - $COL_ID INTEGER NOT NULL PRIMARY KEY, - $COL_MANGA_ID INTEGER NOT NULL, - $COL_MANGA_SIMILAR_MATCHED_IDS TEXT NOT NULL, - $COL_MANGA_SIMILAR_MATCHED_TITLES TEXT NOT NULL, - UNIQUE ($COL_ID) ON CONFLICT REPLACE - )""" - - val createMangaIdIndexQuery: String - get() = "CREATE INDEX ${TABLE}_${COL_MANGA_SIMILAR_MATCHED_IDS}_index ON $TABLE($COL_MANGA_SIMILAR_MATCHED_IDS)" -} diff --git a/app/src/main/java/exh/md/similar/ui/EnableMangaDexSimilarDialogController.kt b/app/src/main/java/exh/md/similar/ui/EnableMangaDexSimilarDialogController.kt deleted file mode 100644 index cc2d80e69..000000000 --- a/app/src/main/java/exh/md/similar/ui/EnableMangaDexSimilarDialogController.kt +++ /dev/null @@ -1,27 +0,0 @@ -package exh.md.similar.ui - -import android.app.Dialog -import android.os.Bundle -import com.afollestad.materialdialogs.MaterialDialog -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.ui.base.controller.DialogController -import exh.md.similar.SimilarUpdateJob -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get - -class EnableMangaDexSimilarDialogController : DialogController() { - - override fun onCreateDialog(savedViewState: Bundle?): Dialog { - val activity = activity!! - val preferences = Injekt.get() - return MaterialDialog(activity) - .title(text = activity.getString(R.string.similar_ask_to_enable_title)) - .message(R.string.similar_ask_to_enable) - .negativeButton(R.string.similar_ask_to_enable_no, activity.getString(R.string.similar_ask_to_enable_no)) - .positiveButton(R.string.similar_ask_to_enable_yes, activity.getString(R.string.similar_ask_to_enable_yes)) { - preferences.mangadexSimilarEnabled().set(true) - SimilarUpdateJob.setupTask(activity) - } - } -} diff --git a/app/src/main/java/exh/md/utils/MdUtil.kt b/app/src/main/java/exh/md/utils/MdUtil.kt index daed4c06b..93b5e7b3d 100644 --- a/app/src/main/java/exh/md/utils/MdUtil.kt +++ b/app/src/main/java/exh/md/utils/MdUtil.kt @@ -42,8 +42,6 @@ class MdUtil { const val cdnUrl = "https://mangadex.org" // "https://s0.mangadex.org" const val baseUrl = "https://mangadex.org" const val apiUrl = "https://api.mangadex.org" - const val apiUrlCdnCache = "https://cdn.statically.io/gh/goldbattle/MangadexRecomendations/master/output/api/" - const val apiUrlCache = "https://raw.githubusercontent.com/goldbattle/MangadexRecomendations/master/output/api/" const val imageUrlCacheNotFound = "https://cdn.statically.io/img/raw.githubusercontent.com/CarlosEsco/Neko/master/.github/manga_cover_not_found.png" const val atHomeUrl = "$apiUrl/at-home/server" const val chapterUrl = "$apiUrl/chapter/" @@ -70,6 +68,10 @@ class MdUtil { }.build().toString() } + const val similarCache = "https://raw.githubusercontent.com/goldbattle/MangadexRecomendations/master/output/api/" + const val similarCacheCdn = "https://cdn.statically.io/gh/goldbattle/MangadexRecomendations/master/output/api/" + const val similarBaseApi = "https://api.similarmanga.com/similar/" + const val groupSearchUrl = "$baseUrl/groups/0/1/" const val apiCovers = "/covers" const val reportUrl = "https://api.mangadex.network/report"