diff --git a/.gitignore b/.gitignore index c6cbe56..b339598 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ *.iml .gradle /local.properties -/.idea/workspace.xml -/.idea/libraries +/.idea/* .DS_Store /build /captures diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 9ce3dc9..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -Lyrically \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 96cc43e..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 0bd7bc6..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 5d19981..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index f4214e9..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/java/com/shkmishra/lyrically/LyricsService.kt b/app/src/main/java/com/shkmishra/lyrically/LyricsService.kt index e0e662b..a7ed65d 100644 --- a/app/src/main/java/com/shkmishra/lyrically/LyricsService.kt +++ b/app/src/main/java/com/shkmishra/lyrically/LyricsService.kt @@ -31,6 +31,8 @@ import java.io.* import java.net.URLEncoder import java.util.* +class LyricsNotFoundException(message: String): Exception(message) + class LyricsService : Service() { @@ -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 @@ -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 { + 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 { + 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("")) - 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("")) - } else { + page = page.substring(page.indexOf("that. -->") + 9) + page = page.substring(0, page.indexOf("")) - 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)]*>".toRegex(), "br2n") temp = temp.replace("]".toRegex(), "]shk") @@ -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