From 213ff028c310d49e9e8729a0812a9cb714e15372 Mon Sep 17 00:00:00 2001 From: UmbrellaalAcademy <165912201+UmbrellaalAcademy@users.noreply.github.com> Date: Mon, 29 Apr 2024 10:37:28 +0530 Subject: [PATCH] Update MangaUpdates.kt --- .../connections/bakaupdates/MangaUpdates.kt | 247 +++++------------- 1 file changed, 60 insertions(+), 187 deletions(-) diff --git a/app/src/main/java/ani/dantotsu/connections/bakaupdates/MangaUpdates.kt b/app/src/main/java/ani/dantotsu/connections/bakaupdates/MangaUpdates.kt index a02214e3..a8c36a0a 100644 --- a/app/src/main/java/ani/dantotsu/connections/bakaupdates/MangaUpdates.kt +++ b/app/src/main/java/ani/dantotsu/connections/bakaupdates/MangaUpdates.kt @@ -1,4 +1,4 @@ -package ani.dantotsu.connections.bakaupdates +package ani.dantotsu.connections.mangaplus import android.content.Context import ani.dantotsu.R @@ -16,235 +16,108 @@ import org.json.JSONException import org.json.JSONObject import java.net.URLEncoder import java.nio.charset.Charset -import java.text.SimpleDateFormat +import ani.dantotsu.connections.anilist.api.FuzzyDate +import okio.ByteString.Companion.encode import java.util.Calendar import java.util.Locale import java.util.TimeZone import java.util.concurrent.TimeUnit -class MangaUpdates { +class MangaPlus { val String.utf8: String get() = URLEncoder.encode(this, Charset.forName("UTF-8").name()) private val Int?.dateFormat get() = String.format("%02d", this) - suspend fun findLatestRelease(media: Media) : ReleaseResponse.Results? { + suspend fun findLatestRelease(media: Media): ReleaseResponse? { return tryWithSuspend { - val query = JSONObject().apply { - try { - put("search", media.mangaName().utf8) - media.startDate?.let { - put( - "start_date", - "${it.year}-${it.month.dateFormat}-${it.day.dateFormat}" - ) - } - put("include_metadata", true) - } catch (e: JSONException) { - e.printStackTrace() - } - } - val res = client.post( - "https://api.mangaupdates.com/v1/releases/search", - json = query + val res = client.get( + "https://mangaplus.shueisha.co.jp/api/series/${media.mangaId()}" ).parsed() - coroutineScope { - res.results?.map { - async(Dispatchers.IO) { - Logger.log(it.toString()) - } - } - }?.awaitAll() - res.results?.first { - it.metadata.series.lastUpdated?.timestamp != null - && (it.metadata.series.latestChapter != null - || (it.record.volume.isNullOrBlank() && it.record.chapter != null)) - } + res } } - suspend fun getSeries(results: ReleaseResponse.Results) : SeriesResponse? { - return results.metadata.series.seriesId?.let { - tryWithSuspend { - val res = client.get( - "https://api.mangaupdates.com/v1/series/$it" - ).parsed() - Logger.log(res.toString()) - res.latestChapter?.let { res } - } - } - } - - fun getLatestChapter(context: Context, results: ReleaseResponse.Results): String { - return results.metadata.series.latestChapter?.let { - context.getString(R.string.chapter_number, it) - } ?: results.record.chapter!!.substringAfterLast("-").trim().let { chapter -> - chapter.takeIf { - it.toIntOrNull() == null - } ?: context.getString(R.string.chapter_number, chapter.toInt()) - } - } - - private suspend fun findReleaseDates(media: Media) : List { - val releaseList = hashMapOf() + suspend fun getSeries(seriesId: String): SeriesResponse? { return tryWithSuspend { - val query = JSONObject().apply { - try { - put("search", media.mangaName().utf8) - media.startDate?.let { - put( - "start_date", - "${it.year}-${it.month.dateFormat}-${it.day.dateFormat}" - ) - } - put("include_metadata", true) - } catch (e: JSONException) { - e.printStackTrace() - } - } - val res = client.post( - "https://api.mangaupdates.com/v1/releases/search", - json = query - ).parsed() - res.results?.filter { - it.record.volume.isNullOrBlank() && it.record.chapter != null - }?.sortedByDescending { it.record.releaseDate }?.forEach { - releaseList[it.record.chapter!!] = it.record.releaseDate - Logger.log(it.toString()) - } - releaseList.values.toList().sortedDescending() - } ?: releaseList.values.toList() - } - - private fun getCalendarInstance(releaseDate: String): Calendar { - val calendar: Calendar = Calendar.getInstance() - val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ROOT) - calendar.timeZone = TimeZone.getDefault() - dateFormat.parse(releaseDate)?.let { calendar.time = it } - return calendar - } - - suspend fun predictRelease(media: Media, latest: Long): Long? { - val releaseDates = findReleaseDates(media) - if (releaseDates.size < 5) return null - releaseDates.forEach { - Logger.log(it) + val res = client.get( + "https://mangaplus.shueisha.co.jp/api/series/$seriesId" + ).parsed() + Logger.log(res.toString()) + res } - val date01 = getCalendarInstance(releaseDates[0]) - val date02 = getCalendarInstance(releaseDates[1]) - val date03 = getCalendarInstance(releaseDates[2]) - val date04 = getCalendarInstance(releaseDates[3]) - val date05 = getCalendarInstance(releaseDates[4]) - val days0102: Long = TimeUnit.MILLISECONDS.toDays(date01.timeInMillis - date02.timeInMillis) - val days0203: Long = TimeUnit.MILLISECONDS.toDays(date02.timeInMillis - date03.timeInMillis) - val days0304: Long = TimeUnit.MILLISECONDS.toDays(date03.timeInMillis - date04.timeInMillis) - val days0405: Long = TimeUnit.MILLISECONDS.toDays(date04.timeInMillis - date05.timeInMillis) + } - val average = (days0102 + days0203 + days0304 + days0405) / 4 + fun getLatestChapter(context: Context, results: ReleaseResponse): String { + return context.getString(R.string.chapter_number, results.metadata.series.latestChapter ?: "") + } + + private suspend fun findLatestReleaseDate(media: Media): Long? { + return tryWithSuspend { + val seriesId = findLatestRelease(media)?.record?.id ?: return@tryWithSuspend null + val series = getSeries(seriesId.toString()) ?: return@tryWithSuspend null + series.lastUpdated ?: return@tryWithSuspend null + } + } + + suspend fun predictRelease(media: Media, latestChapterReleaseDate: Long): Long? { + val latestReleaseDate = findLatestReleaseDate(media) ?: return null + val daysBetweenChapters = latestChapterReleaseDate - latestReleaseDate val date: Calendar = Calendar.getInstance() - date.timeInMillis = latest + date.timeInMillis = latestChapterReleaseDate - return when { - average in 5..14 -> { - latest + 604800000 // 7 days + when { + daysBetweenChapters in 5..14 -> { + date.add(Calendar.DAY_OF_YEAR, 7) } - average in 28..36 -> { + daysBetweenChapters in 28..36 -> { date.add(Calendar.MONTH, 1) - date.timeInMillis } - average in 84..98 -> { + daysBetweenChapters in 84..98 -> { date.add(Calendar.MONTH, 3) - date.timeInMillis } - average >= 358 -> { + daysBetweenChapters >= 358 -> { date.add(Calendar.YEAR, 1) - date.timeInMillis - } - else -> { - null } + else -> return null } + return date.timeInMillis } @Serializable data class ReleaseResponse( - @SerialName("total_hits") - val totalHits: Int?, - @SerialName("page") - val page: Int?, - @SerialName("per_page") - val perPage: Int?, - val results: List? = null + val record: Record, + val metadata: MetaData ) { @Serializable - data class Results( - val record: Record, - val metadata: MetaData + data class Record( + val id: String, + val title: String, + @SerialName("latestChapter") + val lastChapter: String, + @SerialName("lastUpdated") + val lastChapterDate: Long + ) + + @Serializable + data class MetaData( + val series: Series ) { @Serializable - data class Record( - @SerialName("id") - val id: Long, - @SerialName("title") + data class Series( val title: String, - @SerialName("volume") - val volume: String?, - @SerialName("chapter") - val chapter: String?, - @SerialName("release_date") - val releaseDate: String + val latestChapter: Int, + val lastUpdated: Long ) - @Serializable - data class MetaData( - val series: Series - ) { - @Serializable - data class Series( - @SerialName("series_id") - val seriesId: Long?, - @SerialName("title") - val title: String?, - @SerialName("latest_chapter") - val latestChapter: Int?, - @SerialName("last_updated") - val lastUpdated: LastUpdated? - ) { - @Serializable - data class LastUpdated( - @SerialName("timestamp") - val timestamp: Long, - @SerialName("as_rfc3339") - val asRfc3339: String?, - @SerialName("as_string") - val asString: String? - ) - } - } } } @Serializable data class SeriesResponse( - @SerialName("series_id") - val seriesId: Long, - @SerialName("title") val title: String, - @SerialName("description") val description: String?, - @SerialName("latest_chapter") - val latestChapter: Int?, - @SerialName("last_updated") - val lastUpdated: LastUpdated? - ) { - @Serializable - data class LastUpdated( - @SerialName("timestamp") - val timestamp: Long, - @SerialName("as_rfc3339") - val asRfc3339: String?, - @SerialName("as_string") - val asString: String? - ) - } -} \ No newline at end of file + val latestChapter: Int, + val lastUpdated: Long + ) +}