автоматическое обновление страницы в rails для получения текущей песни spotify пользователя

#javascript #ruby-on-rails #ruby #spotify

#javascript #ruby-on-rails #ruby #spotify

Вопрос:

В моем приложении мне нужно обновлять сведения на странице при изменении песни в списке воспроизведения пользователя. Мое текущее решение заключается в использовании setInterval javascript для запроса ajax на страницу. Что приводит к ошибке 500. Есть ли лучшее решение? Кто-нибудь знает, есть ли что-нибудь в spotify api, которое уже обрабатывает это?

web_player.html.erb (представление, которое необходимо обновить автоматически)

 <!DOCTYPE html>
<% @playlists_new.each do |t_info| %>
  <% if t_info[0][0].eql? @current_song %>
    <body>
      <%= link_to 'back', {:controller => "players", :action => "index", :user => @user.to_hash} %>
      <h1>Player</h1>
      <div id="player">
        <div id="track-info">
          <img id="track-cover" src=<%=@player_response['item']['album']['images'][0]['url'].to_s%>></img>
          <h3 id="track-name"><%= @current_song %></h3>
          <h3 id="artist-name"><%= @player_response['item']['artists'][0]['name'] %></h3>
        </div>

        <div id="memories">
          <h3 id="text-memory"><%= t_info[1][0] %></h3>
        </div>
      </div>
    <body>

    <style>
      body {
        background:
          linear-gradient(
            rgba(30, 32, 35, 0.45),
            rgba(30, 32, 35, 0.45)
          ),
          url(<%= t_info[2][0].to_s %>);
      }
    </style>
  <% end %>
<% end %>

<script>
  setInterval(function(){
    $.ajax({
      url: "web_player",
      data: {
        playlist_info: <%= raw(@playlists).html_safe  %>,
        user: <%= raw(@user.to_json).html_safe %>,
      },
      dataType: 'html'
   })
  }, 3000);
</script>
  

players_controller.rb

 require 'net/http'
require 'json'

class PlayersController < ApplicationController

  protect_from_forgery except: :web_player

  def index
    params.require(:user).permit!
    @playlists = Hash.new
    @user = RSpotify::User.new(params[:user]);
    #all tracks with a memory attached
    @tracks = Track.where(:username => @user.display_name).order(:playlist_name)
    #we need to organize the tracks and memories by playlist
    @tracks.each do |t|
      if @playlists[t.playlist_name].nil?
        @playlists[t.playlist_name] = []
      end
      #get playlist URI !!
      @user.playlists.each do |p|
        if p.name.eql? t.playlist_name
          @playlist_uri = p.uri
        end
      end

      @playlists[t.playlist_name] << [t.title, t.memory, t.imageurl, @playlist_uri]
    end

    @player_response = RSpotify.resolve_auth_request(@user.display_name, "me/player/")
    @current_song = @player_response
    if @current_song.nil?
      @current_song = " "
    else
      @current_song = @player_response['item']['name']
    end
  end
  #plays playlist
  def play
    params.require(:user).permit!
    @user = RSpotify::User.new(params[:user]);
    @uri = URI('https://api.spotify.com/v1/me/player/play')
    #request body tells spotify what playlist to play
    @body = {
      "context_uri": params[:playlist_uri]
    }.to_json
    #headers
    req = Net::HTTP::Put.new(@uri.path, initheader = {'Content-Type' =>'application/json', 'Authorization' => 'Bearer '   @user.credentials['token'].to_s})
    req.body = @body
    http = Net::HTTP.new(@uri.host, @uri.port)
    http.use_ssl = true
    response = http.start {|h|
      h.request(req)
    }
    sleep 1.5
    #redirecting to new action so the user can refresh the web player and not restart the playlist
    redirect_to :action => "web_player", :user => @user.to_hash, :playlist_info => params[:playlist_info]
  end

  def web_player
    params.require(:user).permit!
    @user = RSpotify::User.new(params[:user]);
    #get currrent song playing to decide what memory to display
    @player_response = RSpotify.resolve_auth_request(@user.display_name, "me/player/")
    @current_song = @player_response
    if @current_song.nil?
      @current_song = " "
    else
      @current_song = @player_response['item']['name']
    end

    @playlists = params[:playlist_info]
    @playlists_new = []
    #uhh so the playlists hash gets fucked so i'm rebuilding it here hehehe
    (@playlists.length/4).times do |t|
      @playlists_new << [@playlists[(t * 4)], @playlists[(t * 4)   1], @playlists[(t * 4)   2]]
    end
  end
end
  

Кроме того, это хороший запрос, генерируемый действием воспроизведения:

 http://localhost:3000/players/web_player?playlist_info%5B%5D%5B]=Guiltyamp;playlist_info%5B%5D%5B]=farted ehehamp;playlist_info%5B%5D%5B]=amp;playlist_info%5B%5D%5B]=spotify%3Aplaylist:23zfZIyQInLuAyxZzv4taLamp;playlist_info%5B%5D%5B]=Lissomsamp;playlist_info%5B%5D%5B]=farting large %3E%3A)amp;playlist_info%5B%5D%5B]=http%3A%2F/clipart-library.com/data_images/80305.pngamp;playlist_info%5B%5D%5B]=spotify%3Aplaylist:23zfZIyQInLuAyxZzv4taLamp;user%5Bbirthdate]=amp;user%5Bcountry]=amp;user%5Bcredentials%5D%5Bexpires]=trueamp;user%5Bcredentials%5D[expires_at]=1554571172amp;user%5Bcredentials%5D[refresh_token]=AQBuXWgqyvHVsvV0L138RtuvTmc8gKX-PMxvBQ3ovQVyR_40wlPRjvskR6E3s3btEctUYtx44HKMq22Xen7Le_eLg5w70VXl_YTMX-fmCGGnqJqLLWGXAaXrRyqZSBt1mdu2wgamp;user%5Bcredentials%5D%5Btoken]=BQDoUpwrQUsIrc1qDksp--ilhqV6sC0CBnG2e2AZaY1DGj-wgHAWtvnOxkrebfw2C2r5QT-GnAQtJe7sAdH6lc4HF-edb6JnXzy-GZgeIwfYVTugzwNgVQ9uLCTkztPQQu86IsRrEVbtWvdlufVem-S47ms99ZWcujS2fz1Jb6aZGj3_MVtgeicdN5XRuA4zRzYUQoaWxbng_KO9muuUofDramp;user[display_name]=jakeherman-3amp;user%5Bemail]=jakeherman@outlook.comamp;user[external_urls%5D%5Bspotify]=https%3A%2F/open.spotify.com%2Fuser/jakeherman-3amp;user%5Bfollowers%5D%5Bhref]=amp;user%5Bfollowers%5D%5Btotal]=15amp;user%5Bhref]=https%3A%2F/api.spotify.com/v1%2Fusers/jakeherman-3amp;user%5Bid]=jakeherman-3amp;user%5Bimages%5D%5B%5D%5Bheight]=amp;user%5Bimages%5D%5B%5D%5Burl]=https%3A%2F/profile-images.scdn.co%2Fimages%2Fuserprofile%2Fdefault/fa01ec91c49ec1bfc76c3b32b7b7260af83b3903amp;user%5Bimages%5D%5B%5D%5Bwidth]=amp;user%5Bproduct]=amp;user%5Btype]=useramp;user%5Buri]=spotify%3Auser:jakeherman-3
  

И это неверный запрос (ошибка 500), генерируемый методом ajax:

 http://localhost:3000/players/web_player?playlist_info[0%5D%5B]=Guiltyamp;playlist_info[1%5D%5B]=farted ehehamp;playlist_info[2%5D%5B]=amp;playlist_info[3%5D%5B]=spotify%3Aplaylist:23zfZIyQInLuAyxZzv4taLamp;playlist_info[4%5D%5B]=Lissomsamp;playlist_info[5%5D%5B]=farting large %3E:)amp;playlist_info[6%5D%5B]=http%3A%2F/clipart-library.com/data_images/80305.pngamp;playlist_info[7%5D%5B]=spotify%3Aplaylist:23zfZIyQInLuAyxZzv4taLamp;user%5Bbirthdate]=amp;user%5Bcountry]=amp;user[display_name]=jakeherman-3amp;user%5Bemail]=jakeherman@outlook.comamp;user%5Bfollowers%5D%5Bhref]=amp;user%5Bfollowers%5D%5Btotal]=15amp;user%5Bimages%5D[0%5D%5Bheight]=amp;user%5Bimages%5D[0%5D%5Burl]=https%3A%2F/profile-images.scdn.co%2Fimages%2Fuserprofile%2Fdefault/fa01ec91c49ec1bfc76c3b32b7b7260af83b3903amp;user%5Bimages%5D[0%5D%5Bwidth]=amp;user%5Bproduct]=amp;user[external_urls%5D%5Bspotify]=https%3A%2F/open.spotify.com%2Fuser/jakeherman-3amp;user%5Bhref]=https%3A%2F/api.spotify.com/v1%2Fusers/jakeherman-3amp;user%5Bid]=jakeherman-3amp;user%5Btype]=useramp;user%5Buri]=spotify%3Auser:jakeherman-3amp;user%5Bcredentials%5D%5Bexpires]=trueamp;user%5Bcredentials%5D[expires_at]=1554571172amp;user%5Bcredentials%5D[refresh_token]=AQBuXWgqyvHVsvV0L138RtuvTmc8gKX-PMxvBQ3ovQVyR_40wlPRjvskR6E3s3btEctUYtx44HKMq22Xen7Le_eLg5w70VXl_YTMX-fmCGGnqJqLLWGXAaXrRyqZSBt1mdu2wgamp;user%5Bcredentials%5D%5Btoken]=BQDoUpwrQUsIrc1qDksp--ilhqV6sC0CBnG2e2AZaY1DGj-wgHAWtvnOxkrebfw2C2r5QT-GnAQtJe7sAdH6lc4HF-edb6JnXzy-GZgeIwfYVTugzwNgVQ9uLCTkztPQQu86IsRrEVbtWvdlufVem-S47ms99ZWcujS2fz1Jb6aZGj3_MVtgeicdN5XRuA4zRzYUQoaWxbng_KO9muuUofDr
  

Ответ №1:

В скрипте в режиме просмотра веб-плеера я вызываю location.reload() с интервалом в 3 секунды. Более эффективным способом сделать это могло бы быть получение длины текущей песни и изменение интервала на длину трека, я думаю. Но это не учитывает, должен ли пользователь пропустить песню.

 <script>
  setInterval(function(){
   location.reload();
  }, 3000);
</script>
  

Не обязательно доволен этим решением, но пока оно работает.

Комментарии:

1. Как вы говорите, вы могли бы установить время перезагрузки на длину трека, а также добавить прослушиватели событий к элементам управления для обработки пользовательских изменений / приостановки треков. Возможно, добавьте один прослушиватель событий в контейнер панели управления и используйте делегирование событий.