diff --git a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistMutations.kt b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistMutations.kt index 0ba016bd..1ddfbbaa 100644 --- a/app/src/main/java/ani/dantotsu/connections/anilist/AnilistMutations.kt +++ b/app/src/main/java/ani/dantotsu/connections/anilist/AnilistMutations.kt @@ -102,7 +102,7 @@ class AnilistMutations { ?: (currContext()?.getString(ani.dantotsu.R.string.success) ?: "Success") } suspend fun postMessage(userId: Int, text: String, edit: Int? = null,isPrivate: Boolean = false): String { - val encodedText = text.stringSanitizer() + val encodedText = text.replace("","").stringSanitizer() val query = "mutation{SaveMessageActivity(${if (edit != null) "id:$edit," else ""} recipientId:$userId,message:$encodedText,private:$isPrivate){id}}" val result = executeQuery(query) val errors = result?.get("errors") diff --git a/app/src/main/java/ani/dantotsu/media/CharacterAdapter.kt b/app/src/main/java/ani/dantotsu/media/CharacterAdapter.kt index 13b8d3bb..2186791d 100644 --- a/app/src/main/java/ani/dantotsu/media/CharacterAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/CharacterAdapter.kt @@ -33,9 +33,6 @@ class CharacterAdapter( binding.itemCompactRelation.text = whitespace binding.itemCompactImage.loadImage(character.image) binding.itemCompactTitle.text = character.name - binding.root.setOnClickListener { - copyToClipboard(character.name ?: "") - } } override fun getItemCount(): Int = characterList.size @@ -59,6 +56,7 @@ class CharacterAdapter( ).toBundle() ) } + itemView.setOnLongClickListener { copyToClipboard(characterList[bindingAdapterPosition].name ?: ""); true } } } } \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt index cfd9c736..4a7ed075 100644 --- a/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt +++ b/app/src/main/java/ani/dantotsu/media/MediaDetailsViewModel.kt @@ -13,6 +13,7 @@ import ani.dantotsu.media.anime.Episode import ani.dantotsu.media.anime.SelectorDialogFragment import ani.dantotsu.media.manga.MangaChapter import ani.dantotsu.others.AniSkip +import ani.dantotsu.others.Anify import ani.dantotsu.others.Jikan import ani.dantotsu.others.Kitsu import ani.dantotsu.parsers.AnimeSources @@ -99,6 +100,15 @@ class MediaDetailsViewModel : ViewModel() { if (kitsuEpisodes.value == null) kitsuEpisodes.postValue(Kitsu.getKitsuEpisodesDetails(s)) } } + private val anifyEpisodes: MutableLiveData> = + MutableLiveData>(null) + + fun getAnifyEpisodes(): LiveData> = anifyEpisodes + suspend fun loadAnifyEpisodes(s: Int) { + tryWithSuspend { + if (anifyEpisodes.value == null) anifyEpisodes.postValue(Anify.fetchAndParseMetadata(s)) + } + } private val fillerEpisodes: MutableLiveData> = MutableLiveData>(null) diff --git a/app/src/main/java/ani/dantotsu/media/anime/Anime.kt b/app/src/main/java/ani/dantotsu/media/anime/Anime.kt index bee71d03..84672e1b 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/Anime.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/Anime.kt @@ -26,4 +26,5 @@ data class Anime( var slug: String? = null, var kitsuEpisodes: Map? = null, var fillerEpisodes: Map? = null, + var anifyEpisodes: Map? = null, ) : Serializable \ No newline at end of file diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt index 2cb5deca..ecd8ee73 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchFragment.kt @@ -49,6 +49,7 @@ import ani.dantotsu.media.MediaType import ani.dantotsu.navBarHeight import ani.dantotsu.notifications.subscription.SubscriptionHelper import ani.dantotsu.notifications.subscription.SubscriptionHelper.Companion.saveSubscription +import ani.dantotsu.others.Anify import ani.dantotsu.others.LanguageMapper import ani.dantotsu.parsers.AnimeParser import ani.dantotsu.parsers.AnimeSources @@ -213,10 +214,11 @@ class AnimeWatchFragment : Fragment() { if (offline) { media.selected!!.sourceIndex = model.watchSources!!.list.lastIndex } else { - awaitAll( - async { model.loadKitsuEpisodes(media) }, - async { model.loadFillerEpisodes(media) } - ) + val kitsuEpisodes = async { model.loadKitsuEpisodes(media) } + val anifyEpisodes = async { model.loadAnifyEpisodes(media.id) } + val fillerEpisodes = async { model.loadFillerEpisodes(media) } + + awaitAll(kitsuEpisodes, anifyEpisodes, fillerEpisodes) } model.loadEpisodes(media, media.selected!!.sourceIndex) } @@ -231,19 +233,18 @@ class AnimeWatchFragment : Fragment() { val episodes = loadedEpisodes[media.selected!!.sourceIndex] if (episodes != null) { episodes.forEach { (i, episode) -> - fun getThumbnail(episodes: List): List> { - return episodes.mapNotNull { episode -> - val regex = Regex("""Episode\s*(\d+)\s*-\s*(.*)""") - val number = episode.title?.let { - val matchResult = regex.matchEntire(it) - matchResult?.destructured?.component1() - } - number?.let { number to FileUrl[episode.thumbnail] } + if (media.anime?.anifyEpisodes != null) { + if (media.anime!!.anifyEpisodes!!.containsKey(i)) { + episode.desc = media.anime!!.anifyEpisodes!![i]?.desc ?: episode.desc + episode.title = if (MediaNameAdapter.removeEpisodeNumberCompletely( + episode.title ?: "" + ).isBlank() + ) media.anime!!.anifyEpisodes!![i]?.title ?: episode.title else episode.title + ?: media.anime!!.anifyEpisodes!![i]?.title ?: episode.title + episode.thumb = media.anime!!.anifyEpisodes!![i]?.thumb ?: episode.thumb + } } - - val getThumbnail = getThumbnail(media.streamingEpisodes ?: emptyList()) - if (media.anime?.fillerEpisodes != null) { if (media.anime!!.fillerEpisodes!!.containsKey(i)) { episode.title = @@ -253,16 +254,13 @@ class AnimeWatchFragment : Fragment() { } if (media.anime?.kitsuEpisodes != null) { if (media.anime!!.kitsuEpisodes!!.containsKey(i)) { - episode.desc = - media.anime!!.kitsuEpisodes!![i]?.desc ?: episode.desc + episode.desc = media.anime!!.kitsuEpisodes!![i]?.desc ?: episode.desc episode.title = if (MediaNameAdapter.removeEpisodeNumberCompletely( episode.title ?: "" ).isBlank() - ) media.anime!!.kitsuEpisodes!![i]?.title - ?: episode.title else episode.title - ?: media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title - episode.thumb = getThumbnail.find { it.first == i }?.second - ?: media.anime!!.kitsuEpisodes!![i]?.thumb ?: episode.thumb + ) media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title else episode.title + ?: media.anime!!.kitsuEpisodes!![i]?.title ?: episode.title + episode.thumb = media.anime!!.kitsuEpisodes!![i]?.thumb ?: episode.thumb } } } @@ -309,6 +307,10 @@ class AnimeWatchFragment : Fragment() { if (i != null) media.anime?.fillerEpisodes = i } + model.getAnifyEpisodes().observe(viewLifecycleOwner) { i -> + if (i != null) + media.anime?.anifyEpisodes = i + } } fun onSourceChange(i: Int): AnimeParser { diff --git a/app/src/main/java/ani/dantotsu/others/Anify.kt b/app/src/main/java/ani/dantotsu/others/Anify.kt new file mode 100644 index 00000000..cfe74824 --- /dev/null +++ b/app/src/main/java/ani/dantotsu/others/Anify.kt @@ -0,0 +1,46 @@ +package ani.dantotsu.others + +import ani.dantotsu.FileUrl +import ani.dantotsu.Mapper +import ani.dantotsu.client +import ani.dantotsu.media.anime.Episode +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.decodeFromJsonElement + +object Anify { + suspend fun fetchAndParseMetadata(id :Int): Map { + val response = client.get("https://api.anify.tv/content-metadata/$id") + .parsed().map { + Mapper.json.decodeFromJsonElement(it) + } + return response.firstOrNull()?.data?.associate { + it.number.toString() to Episode( + number = it.number.toString(), + title = it.title, + desc = it.description, + thumb = FileUrl[it.img], + ) + } ?: emptyMap() + } + @Serializable + data class AnifyElement ( + @SerialName("providerId") + val providerID: String? = null, + val data: List? = null + ) + + @Serializable + data class Datum ( + val id: String? = null, + val description: String? = null, + val hasDub: Boolean? = null, + val img: String? = null, + val isFiller: Boolean? = null, + val number: Long? = null, + val title: String? = null, + val updatedAt: Long? = null, + val rating: Double? = null + ) +} \ No newline at end of file