Skip to content

Commit

Permalink
Merge branch 'release/0.5.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
boratanrikulu committed Jul 11, 2020
2 parents fdf1159 + b90858a commit 2504415
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 30 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea
.env
.env
database
2 changes: 1 addition & 1 deletion controllers/lyric_controler.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func LyricGet(w http.ResponseWriter, r *http.Request) {
albumImage := r.URL.Query().Get("albumImage")

l := new(models.Lyric)
l.GetLyric(artistName, songName)
l.GetLyricByCheckingDatabase(artistName, songName)

pageData := LyricPageData{
Artist: models.Artist{
Expand Down
12 changes: 9 additions & 3 deletions env.sample
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Spotify API - Application
# s-lyrics
# S-Lyrics, secret keys

# Spotiy
CLIENT_ID=
CLIENT_SECRET=
REDIRECT_URI=
GENIUS_ID

# Genius
GENIUS_ID=
GENIUS_SECRET=
GENIUS_ACCESS=

# Database
DATABASE_ADDRESS=
46 changes: 46 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package main

import (
"bytes"
"fmt"
"log"
"net/http"
"os"
"os/exec"

"github.com/gorilla/mux"
"github.com/joho/godotenv"
Expand All @@ -12,11 +16,18 @@ import (

func main() {
godotenv.Load()

err := cloneOrPullDatabase(os.Getenv("DATABASE_ADDRESS"))
if err != nil {
log.Fatalln(err)
}

r := mux.NewRouter()
r.HandleFunc("/spotify", controllers.SpotifyGet).Methods("GET")
r.HandleFunc("/", controllers.WelcomeGet).Methods("GET")
r.HandleFunc("/logout", controllers.LogoutGet).Methods("GET")
r.PathPrefix("/assets").Handler(http.StripPrefix("/assets/", http.FileServer(http.Dir("./assets/"))))

serve(r, "3000")
}

Expand All @@ -27,3 +38,38 @@ func serve(r *mux.Router, defaultPort string) {
}
http.ListenAndServe(":"+port, r)
}

func cloneOrPullDatabase(databaseURL string) error {
var errOutput bytes.Buffer

if folderExists("./database/.git") {
cmd := exec.Command("git", "pull", "origin", "master")
cmd.Dir = "./database"
cmd.Stderr = &errOutput

err := cmd.Run()
if err != nil {
return fmt.Errorf("%s", errOutput)
}

return nil
}

cmd := exec.Command("git", "clone", databaseURL, "./database")
cmd.Stderr = &errOutput

err := cmd.Run()
if err != nil {
return fmt.Errorf("%s", errOutput)
}

return nil
}

func folderExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return info.IsDir()
}
142 changes: 120 additions & 22 deletions models/lyric.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Lyric struct {
Lines []string
IsAvaible bool
Language string
Translates []Translate
Translates []Translate `json:"-"`
Source string
}

Expand Down Expand Up @@ -46,19 +46,44 @@ type Genius struct {
} `json:"response"`
}

var AllowedTranslationLanguages = []string{"Turkish",
"English",
"Italian",
"Swedish",
"German",
"French",
"Russian",
"Spanish",
}

// Public Methods

func (l *Lyric) GetLyric(artistName string, songName string) {
// Regex for the song name
songName = songRegex(songName)

// Get from lyricstranslates.com
// getFromFirstSource(l, artistName, songName)
getFromFirstSource(l, artistName, songName)

// If there is no lyric on the first source,
// then get it from genius.com
if !l.IsAvaible {
// If there is no lyric on the first source,
// then get it from genius.com
getFromSecondSource(l, artistName, songName)
}

}

func (l *Lyric) GetLyricByCheckingDatabase(artistName string, songName string) {
// Get from local storage source.
getFromDatabase(l, artistName, songName)

if l.IsAvaible {
// Change the source as s-lyrics if it is gotten from database.
l.Source = "s-lyrics.com"
} else {
l.GetLyric(artistName, songName)
}
}

// Private Methods
Expand All @@ -74,6 +99,7 @@ func songRegex(song string) string {
`(?i)\[.*?cover.*?\]`, // Removes all [...cover...]s from song name.
`(?i)\(.*?with.*?\)`, // Removes all (...with...)s from song name.
`(?i)\[.*?with.*?\]`, // Removes all [...with...]s from song name.
// `[-(].+`, // Removes all thigns after '-'.
}

// Run regexs.
Expand All @@ -88,6 +114,28 @@ func songRegex(song string) string {
return song
}

func getFromDatabase(l *Lyric, artistName string, songName string) {
fileName := getFileName(artistName, songName)

f, err := os.Open(fileName)
if err != nil {
return
}
defer f.Close()

b, err := ioutil.ReadAll(f)
if err != nil {
return
}

err = json.Unmarshal(b, l)
if err != nil {
return
}

getTranslationsFromDatabase(l, fileName)
}

func getFromSecondSource(l *Lyric, artistName string, songName string) {
u, _ := url.Parse("https://api.genius.com/search")
q, _ := url.ParseQuery(u.RawQuery)
Expand Down Expand Up @@ -141,9 +189,7 @@ func getFromSecondSource(l *Lyric, artistName string, songName string) {
c.OnHTML("div.song_body-lyrics div.lyrics p", func(e *colly.HTMLElement) {
lines := strings.SplitAfter(e.Text, "\n")
for _, line := range lines {
if line == "\n" {
line = ""
}
line = strings.Trim(strings.TrimSpace(line), "\n")
l.Lines = append(l.Lines, line)
}
})
Expand Down Expand Up @@ -190,13 +236,14 @@ func getFromFirstSource(l *Lyric, artistName string, songName string) {

// Song lyric page.
cc.OnHTML("div#song-body .ltf .par div, .emptyline", func(e *colly.HTMLElement) {
l.Lines = append(l.Lines, e.Text)
line := strings.Trim(strings.TrimSpace(e.Text), "\n")
l.Lines = append(l.Lines, line)
})

// Song's language.
cc.OnHTML(".langsmall-song span.langsmall-languages", func(e *colly.HTMLElement) {
if strings.TrimSpace(e.Text) != "" {
l.Language = e.Text
l.Language = strings.Trim(strings.TrimSpace(e.Text), "\n")
}
})

Expand All @@ -215,32 +262,83 @@ func getFromFirstSource(l *Lyric, artistName string, songName string) {
func getTranslations(l *Lyric, url string) {
c := colly.NewCollector()

allowedTranslationLanguages := "Turkish English Italian Swedish German French"
addedTranslations := []string{}
// Translation list for the song.
c.OnHTML("div.song-node-info li.song-node-info-translate a[href]", func(e *colly.HTMLElement) {
c.OnHTML("div.song-node div.masonry-grid div.song-list-translations-list a[href]", func(e *colly.HTMLElement) {
cc := colly.NewCollector()

// Lyric translations for the song.

cc.OnHTML("div.translate-node-text", func(e *colly.HTMLElement) {
translate := Translate{}
translate.Language = e.ChildText("div.langsmall-song span.mobile-only-inline")
translate.Author.Name = e.ChildText(".authorsubmitted a")
translate.Author.Href = e.ChildAttr(".authorsubmitted a[href]", "href")
if translate.Language != "" {
translate.Title = e.ChildText("h2.title-h2")
e.ForEach(".ltf .par div, .emptyline", func(_ int, e *colly.HTMLElement) {
translate.Lines = append(translate.Lines, e.Text)
language := e.ChildText("div.langsmall-song span.mobile-only-inline")
if !contains(addedTranslations, language) {
translate := Translate{}
translate.Language = language
e.ForEach("div.authorsubmitted a[href]", func(c int, e *colly.HTMLElement) {
if c == 0 {
translate.Author.Name = e.Text
translate.Author.Href = e.Attr("href")
}
})
l.Translates = append(l.Translates, translate)
if translate.Language != "" {
translate.Title = e.ChildText("h2.title-h2")
e.ForEach(".ltf .par div, .emptyline", func(_ int, e *colly.HTMLElement) {
line := strings.Trim(strings.TrimSpace(e.Text), "\n")
translate.Lines = append(translate.Lines, line)
})
l.Translates = append(l.Translates, translate)
addedTranslations = append(addedTranslations, translate.Language)
}
}
})

// TODO
// Fix more-then-one translate issue.
if strings.Contains(allowedTranslationLanguages, e.Text) {
if contains(AllowedTranslationLanguages, e.Text) {
cc.Visit("https://lyricstranslate.com/" + e.Attr("href"))
}
})

c.Visit(url)
}

func getTranslationsFromDatabase(l *Lyric, fileName string) {
for _, translate := range AllowedTranslationLanguages {
fName := fileName + "_" + translate

f, err := os.Open(fName)
if err != nil {
continue
}
defer f.Close()

b, err := ioutil.ReadAll(f)
if err != nil {
continue
}

t := Translate{}
err = json.Unmarshal(b, &t)
if err != nil {
continue
}

l.Translates = append(l.Translates, t)
}
}

func getFileName(artist string, songName string) string {
fileName := artist + "-" + songName + ".json"
fileName = strings.ReplaceAll(fileName, "/", "_")
fileName = strings.ReplaceAll(fileName, "\\", "_")
fileName = "./database/lyrics/" + fileName

return fileName
}

func contains(array []string, value string) bool {
for _, v := range array {
if v == value {
return true
}
}
return false
}
6 changes: 3 additions & 3 deletions views/songs.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h1 class="title song-title">
{{ end }}
{{ if .Song.Lyric.Source }}
<hr>
<p>These lyrics were taken from <a href="https://{{ .Song.Lyric.Source }}">{{ .Song.Lyric.Source }}</a>.</p>
<p>These lyrics were taken from <a href="https://{{ .Song.Lyric.Source }}">{{ .Song.Lyric.Source }}</a></p>
{{ end }}
{{ else }}
<article class="message is-danger">
Expand All @@ -53,9 +53,9 @@ <h1 class="title song-title">
<div id="{{.Language}}" class="card-content" style="display: none;">
<p class="subtitle">{{ .Title }}</p>
{{ range .Lines }}
<p> {{ . }} </p>
<p>{{ . }}</p>
{{ end }}
<p class="translator">Translated by <a href="https://lyricstranslate.com{{ .Author.Href }}">{{ .Author.Name }}.</a></p>
<p class="translator">Translated by <a href="https://lyricstranslate.com{{ .Author.Href }}">{{ .Author.Name }}</a></p>
</div>
{{ end }}
</div>
Expand Down

0 comments on commit 2504415

Please sign in to comment.