Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
/.idea/*
.DS_Store
/build
/captures
1 change: 0 additions & 1 deletion .idea/.name

This file was deleted.

22 changes: 0 additions & 22 deletions .idea/compiler.xml

This file was deleted.

3 changes: 0 additions & 3 deletions .idea/copyright/profiles_settings.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/encodings.xml

This file was deleted.

24 changes: 0 additions & 24 deletions .idea/gradle.xml

This file was deleted.

46 changes: 0 additions & 46 deletions .idea/misc.xml

This file was deleted.

9 changes: 0 additions & 9 deletions .idea/modules.xml

This file was deleted.

12 changes: 0 additions & 12 deletions .idea/runConfigurations.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

165 changes: 110 additions & 55 deletions app/src/main/java/com/shkmishra/lyrically/LyricsService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import java.io.*
import java.net.URLEncoder
import java.util.*

class LyricsNotFoundException(message: String): Exception(message)

class LyricsService : Service() {


Expand Down Expand Up @@ -313,7 +315,12 @@ class LyricsService : Service() {

artist = intent.getStringExtra("artist")
track = intent.getStringExtra("track")
title = "$artist - $track"
// artist entry may be empty
if (artist.isEmpty()) {
title = track
} else {
title = "$artist - $track"
}

titleTV.text = title

Expand Down Expand Up @@ -520,76 +527,126 @@ class LyricsService : Service() {

}

// fetches the lyrics from the Internet
private fun fetchLyricsAsync() {
/*
Currently using 3 providers : azlyrics, genius and lyrics.wikia; in that order
Procedure :
- Google the artist + song name + provider name
- Grab the first result and if it is from the provider we wanted, get the lyrics
*/
asyncJob = launch(UI) {
progressBar.visibility = View.VISIBLE
val result = async(context = CommonPool, parent = asyncJob) {
try {
title = "$artist - $track"
// converts string array to url request
private fun stringArrayToRequest(stringArray : Array<String>) : String {
var request = ""

var url = "https://www.google.com/search?q=" + URLEncoder.encode("lyrics+azlyrics+$artistU+$trackU", "UTF-8") // Google URL
var document = Jsoup.connect(url).userAgent("Mozilla/5.0").timeout(10000).get()
var results = document.select("h3.r > a").first()
for (string in stringArray) {
if (!string.isEmpty()) {
if (stringArray.first() != string) {
request += "+"
}

var lyricURL = results.attr("href").substring(7, results.attr("href").indexOf("&")) // grabbing the first result
val element: Element
var temp: String
println(url)
println(lyricURL)
request += string
}
}

return request
}

if (lyricURL.contains("azlyrics.com/lyrics")) { // checking if from the provider we wanted
document = Jsoup.connect(lyricURL).userAgent(USER_AGENT).get()
var page = document.toString()
// fetches the first result from Google Search
private fun fetchGoogleSearchResult(keywords : Array<String>) : String {
val url = "https://www.google.com/search?q=" + URLEncoder.encode(stringArrayToRequest(keywords), "UTF-8")
println("Searching for keywords in Google Search: " + keywords.joinToString())

page = page.substring(page.indexOf("that. -->") + 9)
page = page.substring(0, page.indexOf("</div>"))
temp = page
} else {
val document = Jsoup.connect(url).userAgent("Mozilla/5.0").timeout(10000).get()
val linkContainers = document.getElementsByTag("a")

url = "https://www.google.com/search?q=" + URLEncoder.encode("genius+" + artistU + "+" + trackU + "lyrics", "UTF-8")
document = Jsoup.connect(url).userAgent("Mozilla/5.0").timeout(10000).get()
for (container in linkContainers) {
if (container.attr("href").substring(0, 7) == "/url?q=") {
val result = container.attr("href").substring(7, container.attr("href").indexOf("&")) // grabbing the first result
println("The first result is: " + result)

results = document.select("h3.r > a").first()
lyricURL = results.attr("href").substring(7, results.attr("href").indexOf("&"))
println(url)
println(lyricURL)
return result
}
}

if (lyricURL.contains("genius")) {
return ""
}

document = Jsoup.connect(lyricURL).userAgent(USER_AGENT).get()
private fun fetchLyricsFromAZLyrics() : String {
val lyricURL = fetchGoogleSearchResult(arrayOf("azlyrics.com", artistU, trackU))

val selector = document.select("div.h2")
for (e in selector) {
e.remove()
}
if (lyricURL.contains("azlyrics.com/lyrics")) {
val document = Jsoup.connect(lyricURL).userAgent(USER_AGENT).get()
var page = document.toString()

element = document.select("div[class=song_body-lyrics]").first()
temp = element.toString().substring(0, element.toString().indexOf("<!--/sse-->"))
} else {
page = page.substring(page.indexOf("that. -->") + 9)
page = page.substring(0, page.indexOf("</div>"))

url = "https://www.google.com/search?q=" + URLEncoder.encode("lyrics.wikia+$trackU+$artistU", "UTF-8")
document = Jsoup.connect(url).userAgent("Mozilla/5.0").timeout(10000).get()
return page
}

results = document.select("h3.r > a").first()
lyricURL = results.attr("href").substring(7, results.attr("href").indexOf("&"))
println(url)
println(lyricURL)
return ""
}

private fun fetchLyricsFromGenius() : String {
val lyricURL = fetchGoogleSearchResult(arrayOf("genius.com", artistU, trackU))

document = Jsoup.connect(lyricURL).userAgent(USER_AGENT).get()
element = document.select("div[class=lyricbox]").first()
temp = element.toString()
if (lyricURL.contains("genius.com")) {
val document = Jsoup.connect(lyricURL).userAgent("Mozilla/5.0").timeout(10000).get() // USER_AGENT doesn't work, returns code 503
val elements = document.select("div[class^=\"Lyrics__Container\"]")

if (elements.size > 0) {
return elements.first().toString()
} else {
return elements.toString()
}
}

return ""
}

private fun fetchLyricsFromSonglyrics() : String {
val lyricURL = fetchGoogleSearchResult(arrayOf("www.songlyrics.com", artistU, trackU))

if (lyricURL.contains("www.songlyrics.com")) {
val document = Jsoup.connect(lyricURL).userAgent(USER_AGENT).get()
return document.select("div[id=songLyricsDiv-outer]").first().toString()
}

return ""
}

// fetches the lyrics from the Internet
private fun fetchLyricsAsync() {
/*
Currently using 3 providers : azlyrics, genius and songlyrics; in that order
Procedure :
- Google the artist + song name + provider name
- Grab the first result and if it is from the provider we wanted, get the lyrics
*/
asyncJob = launch(UI) {
progressBar.visibility = View.VISIBLE
val result = async(context = CommonPool, parent = asyncJob) {
try {
// artist entry may be empty
if (artist.isEmpty()) {
title = track
} else {
title = "$artist - $track"
}

var temp = ""
val fetchFunctions = arrayOf(
::fetchLyricsFromAZLyrics,
::fetchLyricsFromGenius,
::fetchLyricsFromSonglyrics)

for (function in fetchFunctions) {
val result = function()

if (!result.isEmpty()) {
temp = result
break
}
}

// lyrics are not found or track is instrumental
if (temp.isEmpty()) {
throw LyricsNotFoundException("Lyrics are not found for track: " + title)
}

// preserving line breaks
temp = temp.replace("(?i)<br[^>]*>".toRegex(), "br2n")
temp = temp.replace("]".toRegex(), "]shk")
Expand All @@ -599,8 +656,6 @@ class LyricsService : Service() {
lyrics = lyrics.replace("br2n".toRegex(), "\n")
lyrics = lyrics.replace("]shk".toRegex(), "]\n")
lyrics = lyrics.replace("shk\\[".toRegex(), "\n [")
if (lyricURL.contains("genius"))
lyrics = lyrics.substring(lyrics.indexOf("Lyrics") + 6)
} catch (e: Exception) {
e.printStackTrace()
return@async null
Expand Down