Update Mangadex Similar to GoldBattles latest version

This commit is contained in:
Jobobby04
2021-05-12 23:29:14 -04:00
parent e500d0bebf
commit 08f1eff450
25 changed files with 70 additions and 853 deletions
@@ -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<DatabaseHelper>().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<SimilarMangaResponse>().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)
}
}
@@ -0,0 +1,20 @@
package exh.md.handlers.serializers
import kotlinx.serialization.Serializable
@Serializable
data class SimilarMangaResponse(
val id: String,
val title: Map<String, String>,
val contentRating: String,
val matches: List<Matches>,
val updatedAt: String
)
@Serializable
data class Matches(
val id: String,
val title: Map<String, String>,
val contentRating: String,
val score: Double
)
@@ -1,4 +1,4 @@
package exh.md.similar.ui
package exh.md.similar
import android.os.Bundle
import android.view.Menu
@@ -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<MangasPage> {
return runAsObservable({ source.fetchMangaSimilar(manga) })
return runAsObservable({ source.getMangaSimilar(manga.toMangaInfo()) })
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
@@ -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
@@ -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<PreferencesHelper>()
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<SimilarUpdateJob>().setConstraints(constraints).build())
}
// Finally build the periodic request
val request = PeriodicWorkRequestBuilder<SimilarUpdateJob>(
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<SimilarUpdateJob>().build())
}
}
}
@@ -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<NetworkHelper>().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<SimilarFromJson> {
val reader = JsonReader.of(destinationFile.source().buffer())
var processingManga = false
var processingTitles = false
var mangaId: String? = null
var similarIds = mutableListOf<String>()
var similarTitles = mutableListOf<String>()
val similars = mutableListOf<SimilarFromJson>()
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<String>, val similarTitles: List<String>)
/**
* 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))
}
}
}
@@ -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<MangaSimilar>(
SimilarPutResolver(),
SimilarGetResolver(),
SimilarDeleteResolver()
)
class SimilarPutResolver : DefaultPutResolver<MangaSimilar>() {
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<MangaSimilar>() {
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<MangaSimilar>() {
override fun mapToDeleteQuery(obj: MangaSimilar) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
}
@@ -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
}
@@ -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 = "|*|"
}
}
@@ -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<MangaSimilar>) = db.put().objects(similarList).prepare()
fun deleteAllSimilar() = db.delete()
.byQuery(
DeleteQuery.builder()
.table(SimilarTable.TABLE)
.build()
)
.prepare()
}
@@ -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)"
}
@@ -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<PreferencesHelper>()
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)
}
}
}
+4 -2
View File
@@ -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"