Skip to content

Commit

Permalink
Merge pull request #426 from Adolar0042/kamyUpdate
Browse files Browse the repository at this point in the history
feat: update Kamyroll parser to use newest api & hostserver
  • Loading branch information
Adolar0042 authored Oct 18, 2022
2 parents 3ebe1a7 + cb9f468 commit 546f42e
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 51 deletions.
54 changes: 39 additions & 15 deletions app/src/main/java/ani/saikou/anime/ExoplayerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import androidx.core.view.updateLayoutParams
import androidx.lifecycle.lifecycleScope
import androidx.media.session.MediaButtonReceiver
import ani.saikou.*
import ani.saikou.R
import ani.saikou.anilist.Anilist
import ani.saikou.databinding.ActivityExoplayerBinding
import ani.saikou.media.Media
Expand All @@ -61,11 +62,8 @@ import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.ui.CaptionStyleCompat
import com.google.android.exoplayer2.ui.*
import com.google.android.exoplayer2.ui.CaptionStyleCompat.*
import com.google.android.exoplayer2.ui.StyledPlayerView
import com.google.android.exoplayer2.ui.TrackSelectionDialogBuilder
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.HttpDataSource
import com.google.android.exoplayer2.upstream.cache.CacheDataSource
Expand Down Expand Up @@ -101,6 +99,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
private lateinit var exoSource: ImageButton
private lateinit var exoSettings: ImageButton
private lateinit var exoSubtitle: ImageButton
private lateinit var exoSubtitleView: SubtitleView
private lateinit var exoRotate: ImageButton
private lateinit var exoQuality: ImageButton
private lateinit var exoSpeed: ImageButton
Expand Down Expand Up @@ -304,6 +303,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
exoSource = playerView.findViewById(R.id.exo_source)
exoSettings = playerView.findViewById(R.id.exo_settings)
exoSubtitle = playerView.findViewById(R.id.exo_sub)
exoSubtitleView = playerView.findViewById(R.id.exo_subtitles)
exoRotate = playerView.findViewById(R.id.exo_rotate)
exoSpeed = playerView.findViewById(R.id.exo_playback_speed)
exoScreen = playerView.findViewById(R.id.exo_screen)
Expand Down Expand Up @@ -748,6 +748,15 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
epChanging = !it
}

// Subtitle View Margin fix for Kamyroll
if(model.watchSources!!.names[media.selected!!.source] == "Kamyroll" && (settings.kamySubType == 0 || settings.kamySubType == 2)) {
val marginInt = -19 // This gets rounded to -18dp
val margin = (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, marginInt.toFloat(), getResources().getDisplayMetrics())).roundToInt()
exoSubtitleView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = margin
}
}

//Anime Title
animeTitle.text = media.userPreferredName

Expand Down Expand Up @@ -873,6 +882,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
saveData("${media.id}_${media.anime!!.selectedEpisode}", exoPlayer.currentPosition, this)
val intent = Intent(this, PlayerSettingsActivity::class.java).apply {
putExtra("media", media)
putExtra("subtitle", subtitle)
}
finish()
startActivity(intent)
Expand Down Expand Up @@ -1022,20 +1032,34 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
subClick()
}

val sub = if (subtitle != null)
MediaItem.SubtitleConfiguration
.Builder(Uri.parse(subtitle!!.url.url))
.setSelectionFlags(C.SELECTION_FLAG_FORCED)
.setMimeType(
when (subtitle?.type) {
val newSub: Subtitle? = intent.getSerializableExtra("subtitle") as Subtitle?
var sub: MediaItem.SubtitleConfiguration? = null
if(newSub == null && subtitle != null) {
sub = MediaItem.SubtitleConfiguration
.Builder(Uri.parse(subtitle!!.url.url))
.setSelectionFlags(C.SELECTION_FLAG_FORCED)
.setMimeType(
when (subtitle?.type) {
SubtitleType.VTT -> MimeTypes.TEXT_VTT
SubtitleType.ASS -> MimeTypes.TEXT_SSA
SubtitleType.SRT -> MimeTypes.APPLICATION_SUBRIP
else -> MimeTypes.TEXT_UNKNOWN
}
)
.build()
}
if(newSub != null){
sub = MediaItem.SubtitleConfiguration
.Builder(Uri.parse(newSub.url.url))
.setSelectionFlags(C.SELECTION_FLAG_FORCED)
.setMimeType(when (newSub.type) {
SubtitleType.VTT -> MimeTypes.TEXT_VTT
SubtitleType.ASS -> MimeTypes.TEXT_SSA
SubtitleType.SRT -> MimeTypes.APPLICATION_SUBRIP
else -> MimeTypes.TEXT_UNKNOWN
}
)
.build()
else null
}
)
.build()
}

lifecycleScope.launch(Dispatchers.IO) {
ext.onVideoPlayed(video)
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/ani/saikou/anime/SubtitleDialogFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ class SubtitleDialogFragment : BottomSheetDialogFragment() {
"zh-CN" -> "[zh-CN] Chinese (Simplified)"
"tr-TR" -> "[tr-TR] Turkish"
"ar-ME" -> "[ar-ME] Arabic"
"ar-SA" -> "[ar-SA] Arabic (Saudi Arabia)"
"uk-UK" -> "[uk-UK] Ukrainian"
"he-IL" -> "[he-IL] Hebrew"
"pl-PL" -> "[pl-PL] Polish"
"ro-RO" -> "[ro-RO] Romanian"
"sv-SE" -> "[sv-SE] Swedish"
else -> "[${subtitles[position - 1].language}]"
}
model.getMedia().observe(viewLifecycleOwner) { media ->
Expand Down
64 changes: 48 additions & 16 deletions app/src/main/java/ani/saikou/parsers/anime/Kamyroll.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,13 @@ class Kamyroll : AnimeParser() {
params = mapOf(
channelHeader,
"id" to server.embed.url,
localeHeader,
"type" to "adaptive_hls",
"format" to "vtt",
"service" to service,
"format" to when(settings.kamySubType){
0 -> "ass"
1 -> "vtt"
2 -> "srt"
else -> "vtt"
},
),
timeout = 60
).parsed<StreamsResponse>()
Expand Down Expand Up @@ -144,6 +147,12 @@ class Kamyroll : AnimeParser() {
"zh-CN" -> "[zh-CN] Chinese (Simplified)"
"tr-TR" -> "[tr-TR] Turkish"
"ar-ME" -> "[ar-ME] Arabic"
"ar-SA" -> "[ar-SA] Arabic (Saudi Arabia)"
"uk-UK" -> "[uk-UK] Ukrainian"
"he-IL" -> "[he-IL] Hebrew"
"pl-PL" -> "[pl-PL] Polish"
"ro-RO" -> "[ro-RO] Romanian"
"sv-SE" -> "[sv-SE] Swedish"
"" -> ""
else -> "[${it.hardsubLocale}] "
} + if(it.hardsubLocale != "") " Hard-Subbed" else "Soft/No Subs",
Expand All @@ -154,7 +163,12 @@ class Kamyroll : AnimeParser() {
Subtitle(
it.locale ?: return@mapNotNull null,
it.url ?: return@mapNotNull null,
SubtitleType.VTT
when(settings.kamySubType){
0 -> SubtitleType.ASS
1 -> SubtitleType.VTT
2 -> SubtitleType.SRT
else -> SubtitleType.VTT
}
)
}
return VideoContainer(video ?: listOf(), subtitle ?: listOf())
Expand Down Expand Up @@ -215,9 +229,8 @@ class Kamyroll : AnimeParser() {
getHeaders(),
params = mapOf(
channelHeader,
localeHeader,
"limit" to "25",
"query" to query
"query" to encode(query)
)
).parsed<SearchResponse>()
return (res.items ?: listOf()).map { item ->
Expand All @@ -227,7 +240,7 @@ class Kamyroll : AnimeParser() {
ShowResponse(
name = it.title,
link = it.id,
coverUrl = it.images?.posterTall?.getOrNull(5)?.source ?: "",
coverUrl = it.images?.posterTall?.getOrNull(it.images.posterTall.size / 2)?.source ?: "",
extra = if (filter == null) mapOf(type) else mapOf(type, "filter" to filter)
)
}
Expand All @@ -252,35 +265,54 @@ class Kamyroll : AnimeParser() {
12 -> "ru-RU"
13 -> "zh-CN"
14 -> "tr-TR"
15 -> "ar-SA"
16 -> "uk-UK"
17 -> "he-IL"
18 -> "pl-PL"
19 -> "ro-RO"
20 -> "sv-SE"
else -> "en-US"
}
private val locale = when (settings.subtitles) {
true -> subLocale
false -> ""
}
private const val apiUrl = "https://kamyroll.herokuapp.com"
private const val apiUrl = "https://api.kamyroll.tech"
private const val channel = "crunchyroll"
private const val service = "google"

private var headers: Map<String, String>? = null
private val channelHeader = "channel_id" to channel
private val localeHeader = "locale" to locale

suspend fun getHeaders(): Map<String, String> {
private suspend fun newToken(): Map<String, String>{
headers = headers ?: let {
val res = client.post(
"$apiUrl/auth/v1/token",
mapOf(
"authorization" to "Basic vrvluizpdr2eby+RjSKM17dOLacExxq1HAERdxQDO6+2pHvFHTKKnByPD7b6kZVe1dJXifb6SG5NWMz49ABgJA=="
),
data = mapOf(
"refresh_token" to "IV+FtTI+SYR0d5CQy2KOc6Q06S6aEVPIjZdWA6mmO7nDWrMr04cGjSkk4o6urP/6yDmE4yzccSX/rP/OIgDgK4ildzNf2G/pPS9Ze1XbEyJAEUyN+oKT7Gs1PhVTFdz/vYXvxp/oZmLWQGoGgSQLwgoRqnJddWjqk0ageUbgT1FwLazdL3iYYKdNN98BqGFbs/baeqqa8aFre5SzF/4G62y201uLnsElgd07OAh1bnJOy8PTNHpGqEBxxbo1VENqtYilG9ZKY18nEz8vLPQBbin/IIEjKITjSa+LvSDQt/0AaxCkhClNDUX2uUZ8q7fKuSDisJtEyIFDXtuZGFhaaA==",
"grant_type" to "refresh_token",
"scope" to "offline_access",
"device_id" to "com.service.data",
"device_type" to "ani.saikou",
"access_token" to "HMbQeThWmZq4t7w",
)
).parsed<AccessToken>()
mapOf("authorization" to "${res.tokenType} ${res.accessToken}")
}
val timestamp = System.currentTimeMillis()
saveData("kamyrollTokenCreationDate", timestamp)
saveData("kamyrollToken", headers)
return headers as Map<String, String>
}

suspend fun getHeaders(): Map<String, String> {
val timestamp = System.currentTimeMillis()
val lastTime = loadData<Long>("kamyrollTokenCreationDate", currActivity(), false)

if(lastTime == null || (timestamp - lastTime) >= 604800000){
newToken()
}
else{
val headers: Map<String, String>? = loadData<Map<String, String>>("kamyrollToken", currActivity(), false)
return headers!!
}
return headers!!
}

Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/ani/saikou/settings/PlayerSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ data class PlayerSettings(

//Subtitles
var subtitles: Boolean = true,
var kamySubType: Int = 1,
var primaryColor: Int = 4,
var secondaryColor: Int = 0,
var outline: Int = 0,
Expand Down
Loading

0 comments on commit 546f42e

Please sign in to comment.