Class: Ektoplayer::BrowsePage

Inherits:
Object
  • Object
show all
Defined in:
lib/ektoplayer/browsepage.rb

Constant Summary collapse

ALBUM_KEYS =
%w(url title artist date styles cover_url description download_count
archive_urls rating votes tracks).map(&:to_sym).freeze
TRACK_KEYS =
%w(url album_url number title remix artist bpm).map(&:to_sym).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(src) ⇒ BrowsePage

Returns a new instance of BrowsePage.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/ektoplayer/browsepage.rb', line 36

def initialize(src)
   doc = Nokogiri::HTML(src)
   @albums = []

   base_url = doc.css('.wp-pagenavi a')[0]['href'].sub(/\d+$/, '')
   pages = doc.css('.wp-pagenavi .pages')[0].text # -> "Page 1 of 22"
   @current_page_index, last = pages.gsub(/[^\d ]/, '').split()
   @current_page_index, last = @current_page_index.to_i, last.to_i
   @page_urls = (1..last).map do |i| "#{base_url}#{i}" end

   @@styles ||= begin
      doc.xpath('//a[contains(@href, "http") and contains(@href, "/style/")]').map do |a|
         [ a.text, File.basename(a['href']) ]
      end.to_h
   end

   doc.xpath('//div[starts-with(@id, "post-")]').each do |post|
      album = { tracks: [] }
      album[:date] = Date.parse(post.at_css('.d').text).iso8601 rescue nil

      album[:styles] = []
      post.css('.style a').map do |a|
         @@styles[a.text] = File.basename(a['href'])
         album[:styles] << a.text
      end

      album[:description] = post.at_css(?p).
         to_html.sub(/^<p>/, '').sub(/<\/p>$/, '') rescue ''

      begin album[:cover_url] = File.basename(
         URI.parse(post.at_css('.cover')['src']).path
      )
      rescue
      end

      album[:download_count] = post.at_css('.dc strong').text.delete(?,).to_i rescue 0

      post.css('h1 a').each do |a|
         album[:title] = a.text
         album[:url] = File.basename(URI.parse(a['href']).path)
      end 

      album[:archive_urls] = post.css('.dll a').map do |a|
         [ a.text.split[0] , File.basename(a['href']) ]
      end.to_h

      begin
         post.at_css('.postmetadata .d').
            text.scanf('Rated %f%% with %d votes').
            each_slice(2) { |r,v| album[:rating], album[:votes] = r, v }
      rescue
         album[:rating], album[:votes] = 0, 0
      end

      # Extract audio file URLs
      tracklist_urls = []
      post.xpath('.//script').each do |script|
         soundFile = script.text.scan(/soundFile:"(.*)"/)
         if soundFile.size > 0
            soundFile = soundFile[0][0]
            tracklist_urls = Base64.decode64(soundFile).split(?,)
            tracklist_urls.map! { |url| File.basename(url) }
            break
         end
      end
      #
      unless tracklist_urls.size > 0
         # Sometimes there are no tracks:
         # http://www.ektoplazm.com/free-music/dj-basilisk-the-colours-of-ektoplazm
         Application.log(self, "Found no tracks for #{album[:title]} on #{current_page_url}")
      end

      post.css('.tl').each do |album_track_list|
         track = nil
         album_track_list.css('span').each do |ti|
            case ti['class']
            when ?n 
               album[:tracks] << track if track and track[:url]
               track = { url: tracklist_urls.shift }
               track[:number] = ti.text.to_i
            when ?t then track[:title]  = ti.text
            when ?a then track[:artist] = ti.text
            when ?r then track[:remix]  = ti.text
            when ?d then track[:bpm]    = ti.text.scan(/\d+/)[0].to_i rescue nil
            end
         end

         album[:tracks] << track if track and track[:url]
      end

      # extract artist name out ouf album title, set missing artist on album tracks
      unless album[:tracks].all? { |t| t.key?(:artist) }
         if album[:title].include?''
            album[:artist], album[:title] = album[:title].split('', 2)
            album[:tracks].each { |t| t[:artist] ||= album[:artist] }
         else
            album[:tracks].each { |t| t[:artist] ||= 'Unknown Artist' }
         end
      end

      @albums << album
   end
end

Instance Attribute Details

#albumsObject (readonly)

Returns the value of attribute albums.



17
18
19
# File 'lib/ektoplayer/browsepage.rb', line 17

def albums
  @albums
end

#current_page_indexObject (readonly)

Returns the value of attribute current_page_index.



17
18
19
# File 'lib/ektoplayer/browsepage.rb', line 17

def current_page_index
  @current_page_index
end

#page_urlsObject (readonly)

Returns the value of attribute page_urls.



17
18
19
# File 'lib/ektoplayer/browsepage.rb', line 17

def page_urls
  @page_urls
end

Class Method Details

.from_url(url) ⇒ Object



19
20
21
# File 'lib/ektoplayer/browsepage.rb', line 19

def self.from_url(url)
   BrowsePage.new(open(url))
end

Instance Method Details

#current_page_urlObject



26
# File 'lib/ektoplayer/browsepage.rb', line 26

def current_page_url;  @page_urls[@current_page_index - 1] end

#first_page_urlObject



24
# File 'lib/ektoplayer/browsepage.rb', line 24

def first_page_url;    @page_urls[0]    end

#last_page_urlObject



25
# File 'lib/ektoplayer/browsepage.rb', line 25

def last_page_url;     @page_urls[-1]   end

#next_page_urlObject



32
33
34
# File 'lib/ektoplayer/browsepage.rb', line 32

def next_page_url
   @page_urls[@current_page_index + 1] if @current_page_index + 1 < @page_urls.size
end

#prev_page_urlObject



28
29
30
# File 'lib/ektoplayer/browsepage.rb', line 28

def prev_page_url
   @page_urls[@current_page_index - 1] if @current_page_index > 0
end

#stylesObject



23
# File 'lib/ektoplayer/browsepage.rb', line 23

def styles;            @@styles or []   end