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