123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- package main
-
- import (
- "github.com/lamperi/e4bot/spotify"
- "html/template"
- "log"
- "net/http"
- "strings"
- )
-
- var (
- cachedTemplates = template.Must(template.ParseFiles("web/index.html"))
- spotifyClient *spotify.SpotifyClient
- )
-
- func indexHandler(w http.ResponseWriter, r *http.Request) {
- if r.URL.Path != "/" {
- http.Error(w, "Not Found", http.StatusNotFound)
- return
- }
-
- data := struct {
- Username string
- Songs []*struct {
- RoundID int
- RoundName string
- Title string
- Artist string
- URL string
- Sync bool
- }
- }{
- "",
- make([]*struct {
- RoundID int
- RoundName string
- Title string
- Artist string
- URL string
- Sync bool
- }, 0),
- }
-
- session, err := getSession(r)
- if session != nil {
- query := `
- SELECT r.id, r.section, e.artist, e.title, e.spotify_url, e.synced
- FROM public.round r
- LEFT JOIN public.entry e ON r.id = e.round_id
- LEFT JOIN public."user" u ON u.id = e.user_id AND lower(u.username) = lower($1)
- ORDER BY r.start ASC`
- rows, err := getDb().Query(query, session.username)
- if err != nil {
- log.Println("Error while executing query", err)
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- defer rows.Close()
- for i := 0; rows.Next(); i++ {
- row := &struct {
- RoundID int
- RoundName string
- Title string
- Artist string
- URL string
- Sync bool
- }{}
- data.Songs = append(data.Songs, row)
- var (
- artist, title, url *string
- sync *bool
- )
- err = rows.Scan(&data.Songs[i].RoundID, &data.Songs[i].RoundName, &artist, &title, &url, &sync)
- if err != nil {
- log.Println("Error while scanning cursor", err)
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- if artist != nil {
- row.Artist = *artist
- }
- if title != nil {
- row.Title = *title
- }
- if url != nil {
- row.URL = *url
- }
- if sync != nil {
- row.Sync = *sync
- }
- }
- data.Username = session.username
- }
-
- var templates = cachedTemplates
- if true {
- templates = template.Must(template.ParseFiles("web/index.html"))
- }
-
- err = templates.ExecuteTemplate(w, "index.html", data)
- if err != nil {
- log.Println("Error while rendering template", err)
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
- }
-
- func getTrackID(url string) string {
- const externalURLPrefix = "https://open.spotify.com/track/"
- const trackURIPrefix = "spotify:track:"
- if strings.HasPrefix(url, externalURLPrefix) {
- return strings.Split(url, externalURLPrefix)[1]
- } else if strings.HasPrefix(url, trackURIPrefix) {
- return strings.Split(url, trackURIPrefix)[1]
- }
- return url
- }
-
- func updateHandler(w http.ResponseWriter, r *http.Request) {
- if r.URL.Path != "/update" {
- http.Error(w, "Forbidden", http.StatusForbidden)
- return
- }
- session, err := getSession(r)
- if session == nil {
- http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
- return
- }
-
- err = r.ParseForm()
- if err != nil {
- http.Error(w, err.Error(), http.StatusBadRequest)
- return
- }
- round := r.Form.Get("round")
- artist := r.Form.Get("artist")
- title := r.Form.Get("title")
- url := r.Form.Get("url")
-
- if artist == "" && title == "" && url != "" {
- log.Println("Resolving Spotify URL")
- trackID := getTrackID(url)
- err := spotifyClient.Authenticate()
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- track, err := spotifyClient.GetTrack(trackID)
-
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- log.Printf("Found Track with name %v and artists %v\n", track.Name, track.Artists)
- for index, trackArtist := range track.Artists {
- if index == 0 {
- artist = trackArtist.Name
- } else if index == 1 {
- artist = artist + " feat. " + trackArtist.Name
- } else {
- artist = artist + ", " + trackArtist.Name
- }
- }
- title = track.Name
- url = track.ExternalUrls.Spotify
- }
-
- query := `
- INSERT INTO public.entry
- SELECT id, $2, $3, $4, $5, false
- FROM public."user" u
- WHERE lower(u.username) = lower($1)
- ON CONFLICT (user_id, round_id) DO UPDATE SET artist = EXCLUDED.artist, title = EXCLUDED.title, spotify_url = EXCLUDED.spotify_url, synced = EXCLUDED.synced`
- res, err := getDb().Exec(query, session.username, round, artist, title, url)
-
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- affected, err := res.RowsAffected()
- if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
- if affected != 1 {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- return
- }
-
- log.Printf("Updated song for round %s, artist: %s, title: %s, URL: %s",
- round, artist, title, url)
-
- http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
- }
-
- func loginHandler(w http.ResponseWriter, r *http.Request) {
- err := r.ParseForm()
- if err != nil {
- http.Error(w, err.Error(), http.StatusBadRequest)
- return
- }
- username := r.Form.Get("username")
- password := r.Form.Get("password")
- remember := r.Form.Get("remember")
- longer := remember == "remember-me"
-
- cookie, err := tryLogin(username, password, longer)
-
- if err != nil {
- log.Println("Error while trying to login", err.Error())
- http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
- return
- }
-
- http.SetCookie(w, &cookie)
- http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
- }
-
- func webStart(listenAddr string, spot *spotify.SpotifyClient) {
- spotifyClient = spot
-
- mux := http.NewServeMux()
-
- fs := http.FileServer(http.Dir("web"))
- mux.Handle("/css/", fs)
- mux.Handle("/fonts/", fs)
- mux.Handle("/js/", fs)
- mux.Handle("/favicon.ico", fs)
- mux.HandleFunc("/", indexHandler)
- mux.HandleFunc("/update", updateHandler)
- mux.HandleFunc("/login", loginHandler)
-
- http.ListenAndServe(listenAddr, mux)
- }
|