Online M4a Converter (WIP)

This commit is contained in:
shabinder 2021-05-25 00:58:25 +05:30
parent ac209e8509
commit ec8f77d121
5 changed files with 148 additions and 5 deletions

View File

@ -22,6 +22,8 @@ dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlinVersion}") implementation("org.jetbrains.kotlin:kotlin-reflect:${Versions.kotlinVersion}")
implementation("io.ktor:ktor-client-core:1.5.4") implementation("io.ktor:ktor-client-core:1.5.4")
implementation("io.ktor:ktor-client-apache:1.5.4") implementation("io.ktor:ktor-client-apache:1.5.4")
implementation("io.ktor:ktor-client-logging:1.5.4")
implementation(Ktor.slf4j)
implementation("io.ktor:ktor-client-serialization:1.5.4") implementation("io.ktor:ktor-client-serialization:1.5.4")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.1")
// testDeps // testDeps

View File

@ -6,6 +6,10 @@ import io.ktor.client.HttpClient
import io.ktor.client.features.HttpTimeout import io.ktor.client.features.HttpTimeout
import io.ktor.client.features.json.JsonFeature import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer import io.ktor.client.features.json.serializer.KotlinxSerializer
import io.ktor.client.features.logging.DEFAULT
import io.ktor.client.features.logging.LogLevel
import io.ktor.client.features.logging.Logger
import io.ktor.client.features.logging.Logging
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
internal object Common { internal object Common {
@ -24,6 +28,10 @@ internal val client = HttpClient {
} }
) )
} }
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.INFO
}
} }
internal data class GithubFileContent( internal data class GithubFileContent(
val decryptedContent: String, val decryptedContent: String,

View File

@ -0,0 +1,116 @@
package audio_conversion
import analytics_html_img.client
import io.ktor.client.request.forms.formData
import io.ktor.client.request.forms.submitFormWithBinaryData
import io.ktor.client.request.get
import io.ktor.client.request.header
import io.ktor.client.request.headers
import io.ktor.client.statement.HttpStatement
import io.ktor.http.isSuccess
import kotlinx.coroutines.delay
import kotlinx.serialization.json.Json
import utils.debug
interface AudioToMp3 {
@Suppress("EnumEntryName")
enum class Quality(val kbps: String) {
`128KBPS`("128"),
`160KBPS`("160"),
`192KBPS`("192"),
`224KBPS`("224"),
`256KBPS`("256"),
`320KBPS`("320"),
}
suspend fun convertToMp3(
URL: String,
quality: Quality = kotlin.runCatching { Quality.valueOf(URL.substringBeforeLast(".").takeLast(3)) }.getOrNull() ?: Quality.`160KBPS`,
): String? {
val activeHost = getHost() // ex - https://hostveryfast.onlineconverter.com/file/send
val jobLink = convertRequest(URL, activeHost, quality) // ex - https://www.onlineconverter.com/convert/309a0f2bbaeb5687b04f96b6d65b47bfdd
// (jobStatus = "d") == COMPLETION
var jobStatus: String
var retryCount = 20
do {
jobStatus = try {
client.get<String>(
"${activeHost.removeSuffix("send")}${jobLink.substringAfterLast("/")}"
)
} catch (e: Exception) {
e.printStackTrace()
""
}
retryCount--
debug("Job Status", jobStatus)
if (!jobStatus.contains("d")) delay(200) // Add Delay , to give Server Time to process audio
} while (!jobStatus.contains("d", true) && retryCount != 0)
return if (jobStatus.equals("d", true)) {
// Return MP3 Download Link
"${activeHost.removeSuffix("send")}${jobLink.substringAfterLast("/")}/download"
} else null
}
/*
* Response Link Ex : `https://www.onlineconverter.com/convert/11affb6d88d31861fe5bcd33da7b10a26c`
* - to start the conversion
* */
private suspend fun convertRequest(
URL: String,
host: String? = null,
quality: Quality = Quality.`320KBPS`,
): String {
val activeHost = host ?: getHost()
val res = client.submitFormWithBinaryData<String>(
url = activeHost,
formData = formData {
append("class", "audio")
append("from", "audio")
append("to", "mp3")
append("source", "url")
append("url", URL.replace("https:", "http:"))
append("audio_quality", quality.kbps)
}
) {
headers {
header("Host", activeHost.getHostURL().also { debug(it) })
header("Origin", "https://www.onlineconverter.com")
header("Referer", "https://www.onlineconverter.com/")
}
}.run {
debug(this)
dropLast(3) // last 3 are useless unicode char
}
val job = client.get<HttpStatement>(res) {
headers {
header("Host", "www.onlineconverter.com")
}
}.execute()
debug("Schedule Job ${job.status.isSuccess()}")
return res
}
private suspend fun getHost(): String {
return client.get<String>("https://www.onlineconverter.com/get/host") {
headers {
header("Host", "www.onlineconverter.com")
}
}.also { debug("Active Host", it) }
}
private fun String.getHostURL(): String {
return this.removePrefix("https://").substringBeforeLast(".") + "." + this.substringAfterLast(".").substringBefore("/")
}
companion object {
val serializer = Json {
ignoreUnknownKeys = true
isLenient = true
}
}
}

View File

@ -56,6 +56,14 @@ interface JioSaavnRequests {
.formatData(fetchLyrics) .formatData(fetchLyrics)
return serializer.decodeFromJsonElement(SaavnSong.serializer(), data) return serializer.decodeFromJsonElement(SaavnSong.serializer(), data)
} }
suspend fun getSongFromID(
ID: String,
fetchLyrics: Boolean = false
): SaavnSong {
val data = ((serializer.parseToJsonElement(client.get(song_details_base_url + ID)) as JsonObject)[ID] as JsonObject)
.formatData(fetchLyrics)
return serializer.decodeFromJsonElement(SaavnSong.serializer(), data)
}
private suspend fun getSongID( private suspend fun getSongID(
URL: String, URL: String,

View File

@ -1,24 +1,33 @@
package utils package utils
import audio_conversion.AudioToMp3
import io.github.shabinder.fuzzywuzzy.diffutils.FuzzySearch import io.github.shabinder.fuzzywuzzy.diffutils.FuzzySearch
import jiosaavn.JioSaavnRequests
import jiosaavn.models.SaavnSearchResult import jiosaavn.models.SaavnSearchResult
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
// Test Class- at development Time // Test Class- at development Time
fun main(): Unit = runBlocking { fun main(): Unit = runBlocking {
val jioSaavnClient = object : JioSaavnRequests {} /*val jioSaavnClient = object : JioSaavnRequests {}
val resp = jioSaavnClient.searchForSong( val resp = jioSaavnClient.searchForSong(
query = "Filhall" query = "Ye Faasla"
) )
println(resp.joinToString("\n")) println(resp.joinToString("\n"))
val matches = sortByBestMatch( val matches = sortByBestMatch(
tracks = resp, tracks = resp,
trackName = "Filhall", trackName = "Ye Faasla",
trackArtists = listOf("B.Praak", "Nupur Sanon") trackArtists = listOf("Shaan", "Hardy")
) )
debug(matches.toString()) debug(matches.toString())
val link = matches.keys.firstOrNull()?.let {
jioSaavnClient.getSongFromID(it).media_url
}
debug(link.toString())*/
val link = "https://aac.saavncdn.com/787/956c23404206e8f4822827eff5da61a0_320.mp4"
val audioConverter = object : AudioToMp3 {}
val mp3Link = audioConverter.convertToMp3(link.toString())
debug(mp3Link.toString())
} }
private fun sortByBestMatch( private fun sortByBestMatch(