1
0
Fork 0

Working search! Weee!

This commit is contained in:
magnolia-fan 2011-09-10 02:13:02 +04:00
parent 16703a87ec
commit fe7737574d
14 changed files with 349 additions and 344 deletions

View File

@ -1,84 +1,51 @@
class window.Ajax
referer: false
loadArtistData: (name) ->
_search.showSpinner()
name = name.split(' ').join('+')
$.get '/artist/' +name+ '/', (data) ->
if data.status?
if data.status is 'loading'
_search.showArtistPics data.pics
setTimeout () ->
_ajax.loadArtistData name
, 3000
else if data.status is 'corrected'
_ajax.loadArtistData data.page
else if data.status is 'suggestions'
_search.hideSpinner()
_search.showSuggestions data.values
else if data.status == 'loading_failed'
_search.hideSpinner()
_search.showError()
else
_ajax.setArchor '/artist/' +name+ '/'
_pages.renderArtist data
#_search.hideSpinner()
false
loadSearchPage: ->
false
loadSettingsPage: ->
$.get '/templates/settings.html', (data) ->
_ajax.setArchor '/settings/'
_pages.renderSettings _beathaven.localizeHTML $(data)
false
load404Page: ->
$.get '/404.html', (data) ->
$('.data-container .inner').html data
_beathaven.redrawScrollbar()
false
loadAboutPage: ->
$.get '/templates/about.html', (data) ->
_pages.renderTextpage data
_ajax.setTitle 'About'
false
setArchor: (anchor) ->
@referer = this.getAnchor()
window.location.hash = '#' +anchor
getAnchor: () ->
window.location.hash.substring 1;
setTitle: (title) ->
document.title = title+ ' @ BeatHaven'
go: (url) ->
this.setArchor url
false
referer: false
loadSettingsPage: ->
$.get '/templates/settings.html', (data) ->
_ajax.setArchor '/settings/'
_page.renderSettings _beathaven.localizeHTML $(data)
false
load404Page: ->
$.get '/404.html', (data) ->
$('.data-container .inner').html data
false
loadAboutPage: ->
$.get '/templates/about.html', (data) ->
_page.renderTextpage data
_ajax.setTitle 'About'
false
setArchor: (anchor) ->
@referer = this.getAnchor()
window.location.hash = '#' +anchor
getAnchor: () ->
window.location.hash.substring 1;
setTitle: (title) ->
document.title = title+ ' @ BeatHaven'
go: (url) ->
this.setArchor url
false
detectPage: () ->
if m = _ajax.getAnchor().match /\/artist\/(.+)\//
_ajax.loadArtistData m[1]
else if _ajax.getAnchor() == '' or _ajax.getAnchor().match /\/search\//
_ajax.loadSearchPage();
else if _ajax.getAnchor().match /\/settings\//
_ajax.loadSettingsPage()
else if _ajax.getAnchor().match /\/about\//
_ajax.loadAboutPage()
else
_ajax.loadSearchPage()
false
detectPage: () ->
if m = _ajax.getAnchor().match /\/artist\/(.+)\//
_search.loadArtistData m[1]
else if _ajax.getAnchor() == '' or _ajax.getAnchor().match /\/search\//
_ajax.loadSearchPage();
else if _ajax.getAnchor().match /\/settings\//
_ajax.loadSettingsPage()
else if _ajax.getAnchor().match /\/about\//
_ajax.loadAboutPage()
else
#_ajax.loadSearchPage()
false
$('a.data.artist').live 'click', ->
_ajax.loadArtistData $(this).html()
false
$(window).bind 'hashchange', ->
_ajax.detectPage()
false
#_ajax.detectPage()
false

View File

@ -2,12 +2,12 @@
//= require jquery/jplayer/jquery.jplayer/jquery.jplayer
//= require locale
//= require vkontakte
//= require session
//= require vkontakte
//= require ajax
//= require player
//= require search
//= require pages
//= require page
//= require settings
//= require beathaven

View File

@ -5,7 +5,7 @@ window._vkontakte = null
window._ajax = null
window._player = null
window._search = null
window._pages = null
window._page = null
window._settings = null
$ ->
@ -16,7 +16,7 @@ $ ->
window._beathaven = new BeatHaven()
window._beathaven.init()
class BeatHaven
class window.BeatHaven
last_height: false
lang: 'ru'
@ -32,7 +32,7 @@ class BeatHaven
window._search = new Search()
window._pages = new Pages()
window._page = new Page()
window._settings = new Settings()
@ -53,34 +53,7 @@ class BeatHaven
containerId: 'autocomplete-container'
containerItemsId: 'autocomplete-items'
onSelect: ->
_ajax.loadArtistData $('#search').first().val()
adjustSizes: ->
$('.data-container').height $(window).height() - $('.header-container').height() - $('.pulldown').height()
$('.data-container').width $(window).width() - $('.player').width()
$('.player-container').height $(window).height()
$('.playlist').height $(window).height() - $('.player').height() - $('.player-container .additional-controls').height()
$('.data-container').scrollbar()
$('.playlist').scrollbar()
false
checkRedrawScrollbar: ->
focused_id = false
if document.activeElement.id?
focused_id = document.activeElement.id;
outer_height = $('.data-container > div').outerHeight()
if outer_height > 300 and outer_height != _beathaven.last_height
_beathaven.last_height = outer_height
_beathaven.redrawScrollbar()
if focused_id
document.getElementById(focused_id).focus()
focused_id = false
window.setTimeout ->
_beathaven.checkRedrawScrollbar()
false
, 500
false
_search.loadArtistData $('#search').val()
localizeHTML: (obj, lang) ->
unless obj?
@ -102,15 +75,6 @@ class BeatHaven
_locale[id][lang]
else
id
pdShowSpinner: ->
$('.pulldown').html '<div class="pd-spinner"><img src="/images/loader.gif" alt=""/></div>'
false
pdHideSpinner: ->
$('.pulldown').html ''
false
String::htmlsafe = ->
replaces = [

View File

@ -1,4 +1,8 @@
class window.Pages
class window.Page
print: (html) ->
$('#content').html(html)
false
renderArtist: (data) ->
$('#content').html(data)

View File

@ -1,15 +1,37 @@
class window.Search
showSpinner: ->
$('#search').val("").attr(disabled: 'disabled').blur()
$('#search').attr(disabled: 'disabled').blur()
$('#autocomplete-container').hide()
$('#artist-load-spinner').show()
this.hideSuggestions()
false
hideSpinner: ->
$('#search').removeAttr 'disabled'
$('.search_field').first().focus()
$('.search-container img').first().hide()
$('#search').val("").removeAttr 'disabled'
$('#artist-load-spinner').hide()
false
loadArtistData: (name) ->
_search.showSpinner()
name = name.split(' ').join('+')
$.get '/artist/' +name+ '/', (data) ->
if data.status in ['ok', 'loading']
_ajax.setArchor '/artist/' +name+ '/'
_page.print data.html
_search.hideSpinner()
if data.status is 'loading'
setTimeout () ->
_search.loadArtistData name
, 5000
else if data.status is 'corrected'
_search.loadArtistData data.correct_name
else if data.status is 'suggestions'
_search.hideSpinner()
_page.print data.html
else if data.status == 'fail'
_search.hideSpinner()
_page.print data.html
false
showSuggestions: (values) ->
@ -59,13 +81,10 @@ $('.search').live 'click', ->
_beathaven.adjustSizes()
_beathaven.redrawScrollbar()
false
$('.search_form').live 'submit', ->
$('.autocomplete-container').remove()
_ajax.loadArtistData $('.search_field').first().val()
false
$('.suggestions a').live 'click', ->
$('.search_field').first().val $(this).text()
$('#search-form').live 'submit', ->
$('#autocomplete-container').remove()
_search.loadArtistData $('#search').val()
false
$('.data.artist').live 'click', ->
_ajax.go('/artist/'+$(this).text().replace(' ', '+')+'/');
false;
_search.loadArtistData $(this).html()
false

View File

@ -1,140 +1,140 @@
class window.Vkontakte
qr: null
api_id: null
constructor: (@api_id) ->
getApiId: ->
@api_id
init: ->
@qr = []
window.vkAsyncInit = ->
VK.init apiId: _vkontakte.getApiId()
VK.Auth.getLoginStatus (response) ->
_vkontakte.authInfo(response)
qr: null
api_id: null
constructor: (@api_id) ->
getApiId: ->
@api_id
init: ->
@qr = []
window.vkAsyncInit = ->
VK.init apiId: _vkontakte.getApiId()
VK.Auth.getLoginStatus (response) ->
_vkontakte.authInfo(response)
setTimeout ->
$('#vk_api_transport').append('<script async="async" type="text/javascript" src="http://vkontakte.ru/js/api/openapi.js"></script>')
, 0
authInfo: (response) ->
if typeof response isnt 'undefined' and response.session
_session = new Session(response.session)
setTimeout ->
$('#vk_api_transport').append('<script async="async" type="text/javascript" src="http://vkontakte.ru/js/api/openapi.js"></script>')
, 0
authInfo: (response) ->
if typeof response isnt 'undefined' and response.session
_session = new Session(response.session)
$('#vk_login, .auth-notice').hide()
_session.query '/user/auth', {}, (ar) ->
if ar.newbie
VK.Api.call 'getVariable', key: 1281, (r) ->
_session.query '/user/update', name: r.response, (ar2) ->
_session.setUser ar2.user
$('.header-container .hello .greating')
.html _beathaven.ls('HELLO')+', <span class="settings">' +(if _session.getUser().name then _session.getUser().name else '%username%')+ '</span>!'
window._session = _session
_ajax.detectPage()
$('.fullscreen').hide();
else
_session.setUser ar.user
$('.header-container .hello').show()
$('.header-container .hello .greating')
.html _beathaven.ls('HELLO')+', <span class="settings">' +(if _session.getUser().name then _session.getUser().name else '%username%')+ '</span>!'
window._session = _session
_ajax.detectPage()
$('.fullscreen').hide();
if response.session.expire?
setTimeout ->
_vkontakte.auth()
false
, response.session.expire * 1000 - new Date().getTime() + 1000
else
_session = new Session({})
_session.setUser {}
$('#vk_login').css display: 'block'
$('.auth-notice').css('left', $('#vk_login').offset().left).show()
$('.header-container .hello').hide()
window._session = _session
_ajax.detectPage()
$('.fullscreen').hide();
auth: ->
VK.Auth.getLoginStatus (response) ->
_vkontakte.authInfo(response)
false
, 8
false
loadTracksData: (artist, track, duration, callback) ->
track_prepared = track.replace(/\(.*\)/i, '').split('/')[0];
query = artist+' '+track_prepared;
if url = _vkontakte.getQR query
callback url
else
VK.Api.call 'audio.search', q: query, (r) ->
url = _vkontakte.matchPerfectResult r.response, artist, track, duration
_vkontakte.addQR query, url
callback url
matchPerfectResult: (data, artist, track, duration) ->
duration = duration.split ':'
duration = parseInt(duration[0], 10) * 60 + parseInt(duration[1], 10)
best_score = 0;
best_result = null;
for item in data
if typeof item is 'object'
score = 0;
item.artist = item.artist.trim();
item.title = item.title.trim();
if item.artist == artist
score += 10
else if item.artist.split(artist).length is 2
score += 5
else if item.title.split(artist).length is 2
score += 4
if item.title == track
score += 10
else if item.title.split(track).length is 2
score += 5
if parseInt(item.duration, 10) == duration
score += 15
else
delta = Math.abs parseInt(item.duration, 10) - duration
score += (10 - delta) if delta < 10
if score > best_score
best_score = score
best_result = item
if score is 35
return best_result.url
$('#vk_login, .auth-notice').hide()
_session.query '/user/auth', {}, (ar) ->
if ar.newbie
VK.Api.call 'getVariable', key: 1281, (r) ->
_session.query '/user/update', name: r.response, (ar2) ->
_session.setUser ar2.user
$('.header-container .hello .greating')
.html _beathaven.ls('HELLO')+', <span class="settings">' +(if _session.getUser().name then _session.getUser().name else '%username%')+ '</span>!'
window._session = _session
_ajax.detectPage()
$('.fullscreen').hide();
else
_session.setUser ar.user
$('.header-container .hello').show()
$('.header-container .hello .greating')
.html _beathaven.ls('HELLO')+', <span class="settings">' +(if _session.getUser().name then _session.getUser().name else '%username%')+ '</span>!'
window._session = _session
_ajax.detectPage()
$('.fullscreen').hide();
if response.session.expire?
setTimeout ->
_vkontakte.auth()
false
, response.session.expire * 1000 - new Date().getTime() + 1000
else
_session = new Session({})
_session.setUser {}
$('#vk_login').css display: 'block'
$('.auth-notice').css('left', $('#vk_login').offset().left).show()
$('.header-container .hello').hide()
window._session = _session
_ajax.detectPage()
$('.fullscreen').hide();
auth: ->
VK.Auth.getLoginStatus (response) ->
_vkontakte.authInfo(response)
false
, 8
false
loadTracksData: (artist, track, duration, callback) ->
track_prepared = track.replace(/\(.*\)/i, '').split('/')[0];
query = artist+' '+track_prepared;
if url = _vkontakte.getQR query
callback url
else
VK.Api.call 'audio.search', q: query, (r) ->
url = _vkontakte.matchPerfectResult r.response, artist, track, duration
_vkontakte.addQR query, url
callback url
matchPerfectResult: (data, artist, track, duration) ->
duration = duration.split ':'
duration = parseInt(duration[0], 10) * 60 + parseInt(duration[1], 10)
best_score = 0;
best_result = null;
for item in data
if typeof item is 'object'
score = 0;
item.artist = item.artist.trim();
item.title = item.title.trim();
if item.artist == artist
score += 10
else if item.artist.split(artist).length is 2
score += 5
else if item.title.split(artist).length is 2
score += 4
if item.title == track
score += 10
else if item.title.split(track).length is 2
score += 5
if parseInt(item.duration, 10) == duration
score += 15
else
delta = Math.abs parseInt(item.duration, 10) - duration
score += (10 - delta) if delta < 10
if score > best_score
best_score = score
best_result = item
if score is 35
return best_result.url
return best_result.url
addQR: (query, url) ->
@qr[query] = url;
getQR: (query) ->
if @qr[query]?
@qr[query]
false
return best_result.url
addQR: (query, url) ->
@qr[query] = url;
getQR: (query) ->
if @qr[query]?
@qr[query]
false
$('#vk_login, .auth-notice').live 'click', ->
VK.Auth.login (response) ->
_vkontakte.authInfo(response)
false
, 8
false
VK.Auth.login (response) ->
_vkontakte.authInfo(response)
false
, 8
false
$('#vk_logout').live 'click', ->
_ajax.go '/search/';
VK.Auth.logout (response) ->
_vkontakte.authInfo(response)
false
false
_ajax.go '/search/';
VK.Auth.logout (response) ->
_vkontakte.authInfo(response)
false
false

View File

@ -15,9 +15,4 @@
left: 50%;
margin: -32px 0 0 -32px;
}
}
.artist-loader {
float: right;
margin: -26px 0 0 10px;
}

View File

@ -18,4 +18,14 @@
}
}
}
}
#artist-load-spinner {
display: none;
float: right;
margin: -26px 0 0 10px;
}
.suggestions a {
cursor: pointer;
}

View File

@ -3,82 +3,114 @@ require 'open-uri'
class ArtistController < ApplicationController
@@default_album_types = ['Album', 'Soundtrack']
def data
data = {}
@data = {
:status => '',
:correct_name => '',
:html => ''
}
@loading = false
# Bad params
if params[:name].nil? or params[:name].length == 0
render :json => {status: 'loading_failed', pics: []}
@data[:status] = 'loading_failed';
render :json => @data
return
end
# Searching for artist
name = params[:name].gsub('%20', ' ').gsub('+', ' ').gsub('.html', '')
artist = Artist.find_by_name(name)
if artist and artist.status == 0
pics = []
pics << artist.pic_url unless artist.pic_url.nil?
unless artist.albums.empty?
artist.albums.each do |album|
pics << album.pic_url unless album.pic_url.nil? or album.pic_url.empty?
end
end
render :json => {status: 'loading', pics: pics}
return
elsif artist and artist.status == 2
render :json => {status: 'loading_failed', pics: []}
return
end
unless artist
@artist = Artist.find_by_name(name)
# Artist not found
unless @artist
results = ArtistController.musicBrainzExactSearch(name)
if results.empty?
render :json => {status: 'not found'}
return
@data[:status] = 'not_found'
render :json => @data
elsif results[0][:name] != name and (results[0][:name].downcase == name.downcase or results[0][:name].downcase == 'the '+ name.downcase)
@data[:status] = 'corrected'
@data[:correct_name] = results[0][:name]
render :json => @data
elsif results[0][:name] == name
# Saving artist and queueing job
artist = Artist.new
artist.name = name
artist.status = 0
artist.save
@artist = Artist.new
@artist.name = name
@artist.status = 0
@artist.save
Delayed::Job.enqueue LoadArtistJob.new(name)
render :json => {status: 'loading', pics: []}
return
elsif results[0][:name].downcase == name.downcase or results[0][:name].downcase == 'the '+ name.downcase
render :json => {status: 'corrected', page: results[0][:name]}
return
# Rendering loading info
@artist = { :artist => @artist, :albums => [] }
@loading = true
@data[:status] = 'loading'
@data[:html] = (render_to_string :partial => 'page').gsub(/\n\s+/, '').gsub(/\n/, '')
render :json => @data
else
render :json => {status: 'suggestions', values: results.take(5)}
return
@suggestions = results.take(5)
@data[:status] = 'suggestions'
@data[:html] = (render_to_string :partial => 'suggestions').gsub(/\n\s+/, '').gsub(/\n/, '')
render :json => @data
end
return
end
data[:artist] = {id: artist.id, name: artist.name, desc: ActionController::Base.helpers.strip_tags(artist.desc), pic: artist.pic_url}
data[:albums] = []
albums = artist.albums
albums.each do |album|
if @artist and @artist.status == 2
@data[:status] = 'fail'
@data[:html] = (render_to_string :partial => 'fail').gsub(/\n\s+/, '').gsub(/\n/, '')
render :json => @data
return
end
if @artist.status == 1
@data[:status] = 'ok'
else
@data[:status] = 'loading'
@loading = true
end
ap @artist
@data[:html] = buildArtistHTML(@artist)
render :json => @data
end
def buildArtistHTML artist
@artist[:artist] = {
id: artist.id,
name: artist.name,
desc: ActionController::Base.helpers.strip_tags(artist.desc),
pic: artist.pic_url
}
@artist[:albums] = []
artist.albums.each do |album|
if @@default_album_types.include? album.album_type
tmp_album = {id: album.id, name: album.name, year: album.year, pic: album.pic_url}
album_tracks = []
bonus_tracks = []
album.tracks.each do |track|
tmp_track = {id: track.id, name: track.name, live: track.live, acoustic: track.acoustic}
if track.length
time = (track.length / 1000).round
time_m = (time / 60).floor
time_s = time - time_m * 60
tmp_track[:duration] = time_m.to_s + ':' + (time_s < 10 ? '0' : '') + time_s.to_s
else
tmp_track[:duration] = '0:00'
end
tmp_track[:duration] = formatTrackDuration(track.length)
(track.bonus == 0 ? album_tracks : bonus_tracks) << tmp_track
end
tmp_album[:tracks] = {album: album_tracks, bonus: bonus_tracks}
data[:albums] << tmp_album
@artist[:albums] << tmp_album
end
end
@data = data
respond_to do |format|
format.html { render :partial => 'data' }
format.json { render :json => @data }
(render_to_string :partial => 'page').gsub(/\n\s+/, '').gsub(/\n/, '')
end
def formatTrackDuration length
if length
time = (length / 1000).round
time_m = (time / 60).floor
time_s = time - time_m * 60
time_m.to_s + ':' + (time_s < 10 ? '0' : '') + time_s.to_s
else
'0:00'
end
end
def autocomplete
autocomplete = ArtistController.getLastFmAutocomplete(params[:query])
autocomplete = getLastFmAutocomplete(params[:query])
return render :nothing => true if autocomplete.nil?
suggestions = []
autocomplete["response"]["docs"].each do |doc|
@ -90,16 +122,16 @@ class ArtistController < ApplicationController
}
end
def self.getLastFmAutocomplete query
def getLastFmAutocomplete query
return nil if query.nil? or query.strip.empty?
json = ActiveSupport::JSON.decode(open(
'http://www.last.fm/search/autocomplete' <<
'?rows=30&q=' << URI.escape(query)
).read)
return json.empty? ? nil : json
json.empty? ? nil : json
end
def self.musicBrainzSearch(query)
def musicBrainzSearch(query)
begin
response = ActiveSupport::JSON.decode(open('http://search.test.musicbrainz.org/ws/2/artist/?fmt=json&query='+ URI.escape(query).gsub(/\&/, '%26').gsub(/\?/, '%3F') +'~&limit=100').read)
artists = []
@ -108,7 +140,7 @@ class ArtistController < ApplicationController
end
artists.take(10)
rescue
return {}
{}
end
end
@ -140,7 +172,7 @@ class ArtistController < ApplicationController
artists.sort! { |a, b| b[:weight] <=> a[:weight] }
artists.take(10)
rescue
return {}
{}
end
end
end

View File

@ -18,9 +18,8 @@ class ImportController < ApplicationController
lastfm = Lastfm.new(@@lastfm_api_key, @@lastfm_secret)
artist = Artist.find_or_create_by_name(name)
begin
begin
# Get artist info
artist_mb_data = ArtistController.musicBrainzExactSearch(name).first
begin
@ -30,13 +29,16 @@ class ImportController < ApplicationController
ap e.message
ap e.backtrace
end
# Save artist
artist.desc = artist_lastfm['bio']['summary']
artist.pic_url = artist_lastfm['image'][3]['content']
artist.artist_type = artist_mb['artist']['type']
artist.mbid = artist_mb_data[:mbid]
artist.save! unless dry_run
end
begin
# Get albums from MB
release_groups_mb = brainz.release_group(nil, :artist => artist_mb_data[:mbid], :limit => 500)
@ -167,7 +169,7 @@ class ImportController < ApplicationController
tracks_mb.each do |mb_track|
unless ['[silence]', '[untitled]'].include? mb_track['recording']['title']
track = Track.new
track.name = mb_track['recording']['title'].gsub(/\s\\\s\[.*?\]/, '')
track.name = mb_track['recording']['title'].gsub(/\s\/\s\[.*?\]/, '')
track.album_id = album.id
track.position = mb_track['position']
track.length = mb_track['length'] unless mb_track['length'].nil?

View File

@ -0,0 +1,2 @@
.alert-message.error
%p Something very bad happened, sorry :(

View File

@ -1,11 +1,15 @@
- if @loading
.alert-message.warning
%p Artist info is loading for the first time. Please, be patient! :)
.row.artist-info
.span4.columns.pic
%img{ :src => @data[:artist][:pic] }
= image_tag @artist[:artist][:pic] unless @artist[:artist][:pic].nil?
.span7.columns.desc
%h2= @data[:artist][:name]
= @data[:artist][:desc]
%h2= @artist[:artist][:name]
= @artist[:artist][:desc] unless @artist[:artist][:desc].nil?
- @data[:albums].each do |album|
- @artist[:albums].each do |album|
.row.album
.span4.columns.art
%img{ :src => album[:pic] }
@ -17,4 +21,4 @@
- album[:tracks][:album].each do |track|
%tr
%td.song-title= track[:name]
%td.song-duration= track[:duration]
%td.song-duration= track[:duration]

View File

@ -0,0 +1,12 @@
.alert-message.warning
%p Made a typo?
%ul.suggestions
- @suggestions.each do |artist|
%li
%a.data.artist= artist[:name]
&nbsp;(
= artist[:type]
)
%br
%p= artist[:desc]

View File

@ -21,9 +21,9 @@
%a{ :href => "http://blog.beathaven.org/", :"data-ls" => "NEWS" } Blog
%li
%a.about{ :href => "#/about/" } About
%form{ :action => "" }
%form#search-form{ :action => "" }
%input#search{ :type => "text", :placeholder => "Search" }
.artist-loader
#artist-load-spinner
= image_tag "artist_loader.gif"
%ul.nav.secondary-nav
%li.dropdown
@ -86,9 +86,3 @@
= image_tag "loader.gif"
#vk_api_transport
<!-- Yandex.Metrika counter -->
<script type="text/javascript">var yaParams = {};</script><div style="display:none;"><script type="text/javascript">(function(w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter7596904 = new Ya.Metrika({id:7596904, enableAll: true,params:window.yaParams||{ }}); } catch(e) { } }); })(window, "yandex_metrika_callbacks");</script></div><script src="//mc.yandex.ru/metrika/watch.js" type="text/javascript" defer="defer"></script><noscript><div><img src="//mc.yandex.ru/watch/7596904" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->