notu 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/VERSION +1 -1
 - data/lib/notu/api.rb +25 -0
 - data/lib/notu/json_document.rb +11 -0
 - data/lib/notu/library.rb +8 -37
 - data/lib/notu/loved_tracks.rb +18 -10
 - data/lib/notu/most_played_tracks.rb +21 -28
 - data/lib/notu/recent_tracks.rb +34 -0
 - data/lib/notu.rb +3 -5
 - data/notu.gemspec +0 -1
 - metadata +5 -26
 - data/lib/notu/html_document.rb +0 -19
 - data/lib/notu/listing.rb +0 -32
 - data/lib/notu/played_tracks.rb +0 -26
 - data/lib/notu/unknown_username_error.rb +0 -14
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: efbddd2bb568278da60c542fd1046d39a61d200bf1ca1a20614e7135ac07e66f
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 4c14831c8b1526a402cf47870e64d17fb5e3ffa4b04d0f2ecaefb30d493de4e3
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 60c8869371be7e6b80a4b8f8b26ebfa2406f63cb576d7788cf6aeacb6d963c3f4d534455a5ae33bca7ea0a33236a0bb6ab529980fc3697ba302062e764f96d0c
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 8343035fb3d9a5ce7e9bba05676f13b0265ace6f514e2e492aa5280eeae0ddc25990eb553adf39f698f66767f4da2d5a5d55523e6b04d2fef428cb47129ece3b
         
     | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
      
 1 
     | 
    
         
            +
            4.0.0
         
     | 
    
        data/lib/notu/api.rb
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Notu
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class Api
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                DEFAULT_KEY = '91f5d6a201de58e0c0a0d858573dddf0'.freeze
         
     | 
| 
      
 6 
     | 
    
         
            +
                FORMAT = 'json'.freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
                HOST = 'ws.audioscrobbler.com'.freeze
         
     | 
| 
      
 8 
     | 
    
         
            +
                VERSION = '2.0'.freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :key
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(key: DEFAULT_KEY)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @key = key.try(:squish).presence || raise(Error.new('API key must be specified'))
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def url(params = {})
         
     | 
| 
      
 17 
     | 
    
         
            +
                  params = (params || {}).symbolize_keys
         
     | 
| 
      
 18 
     | 
    
         
            +
                  params.merge!(api_key: key, format: FORMAT)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  query_string = params.map { |name, value| "#{CGI.escape(name.to_s)}=#{CGI.escape(value.to_s)}" }.join('&')
         
     | 
| 
      
 20 
     | 
    
         
            +
                  "https://#{HOST}/#{VERSION}?#{query_string}"
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/notu/library.rb
    CHANGED
    
    | 
         @@ -2,14 +2,11 @@ module Notu 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
              class Library
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
                 
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :api, :username
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
                 
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                  @semaphore = Mutex.new
         
     | 
| 
       11 
     | 
    
         
            -
                  options = options.symbolize_keys
         
     | 
| 
       12 
     | 
    
         
            -
                  self.username = options[:username]
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(username:, api: Api.new)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @api = api.presence || raise(Error.new('API must be specified'))
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @username = username.try(:squish).presence || raise(Error.new('Username must be specified'))
         
     | 
| 
       13 
10 
     | 
    
         
             
                end
         
     | 
| 
       14 
11 
     | 
    
         | 
| 
       15 
12 
     | 
    
         
             
                def loved_tracks
         
     | 
| 
         @@ -20,38 +17,12 @@ module Notu 
     | 
|
| 
       20 
17 
     | 
    
         
             
                  MostPlayedTracks.new(self, options)
         
     | 
| 
       21 
18 
     | 
    
         
             
                end
         
     | 
| 
       22 
19 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
                def  
     | 
| 
       24 
     | 
    
         
            -
                   
     | 
| 
       25 
     | 
    
         
            -
                end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                def url(options = {})
         
     | 
| 
       28 
     | 
    
         
            -
                  options = options.symbolize_keys
         
     | 
| 
       29 
     | 
    
         
            -
                  path = options[:path].presence
         
     | 
| 
       30 
     | 
    
         
            -
                  query = options[:query].presence
         
     | 
| 
       31 
     | 
    
         
            -
                  query = options[:query].map { |name, value| "#{CGI.escape(name.to_s)}=#{CGI.escape(value.to_s)}" }.join('&') if options[:query].is_a?(Hash)
         
     | 
| 
       32 
     | 
    
         
            -
                  "https://#{HOST}/user/#{username}".tap do |url|
         
     | 
| 
       33 
     | 
    
         
            -
                    if path.present?
         
     | 
| 
       34 
     | 
    
         
            -
                      url << '/' unless path.starts_with?('/')
         
     | 
| 
       35 
     | 
    
         
            -
                      url << path
         
     | 
| 
       36 
     | 
    
         
            -
                    end
         
     | 
| 
       37 
     | 
    
         
            -
                    if query.present?
         
     | 
| 
       38 
     | 
    
         
            -
                      url << '?' << query
         
     | 
| 
       39 
     | 
    
         
            -
                    end
         
     | 
| 
       40 
     | 
    
         
            -
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                def recent_tracks
         
     | 
| 
      
 21 
     | 
    
         
            +
                  RecentTracks.new(self)
         
     | 
| 
       41 
22 
     | 
    
         
             
                end
         
     | 
| 
       42 
23 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                 
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                def username=(value)
         
     | 
| 
       46 
     | 
    
         
            -
                  @semaphore.synchronize do
         
     | 
| 
       47 
     | 
    
         
            -
                    @username = value.to_s.strip.downcase
         
     | 
| 
       48 
     | 
    
         
            -
                    raise UnknownUsernameError.new(value) if username !~ /^[a-z0-9_]+$/
         
     | 
| 
       49 
     | 
    
         
            -
                    begin
         
     | 
| 
       50 
     | 
    
         
            -
                      HtmlDocument.get(url)
         
     | 
| 
       51 
     | 
    
         
            -
                    rescue
         
     | 
| 
       52 
     | 
    
         
            -
                      raise UnknownUsernameError.new(value)
         
     | 
| 
       53 
     | 
    
         
            -
                    end
         
     | 
| 
       54 
     | 
    
         
            -
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                def url(params = {})
         
     | 
| 
      
 25 
     | 
    
         
            +
                  api.url((params || {}).symbolize_keys.merge(user: username))
         
     | 
| 
       55 
26 
     | 
    
         
             
                end
         
     | 
| 
       56 
27 
     | 
    
         | 
| 
       57 
28 
     | 
    
         
             
              end
         
     | 
    
        data/lib/notu/loved_tracks.rb
    CHANGED
    
    | 
         @@ -2,25 +2,33 @@ module Notu 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
              class LovedTracks
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
                include  
     | 
| 
      
 5 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :library
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(library)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  raise ArgumentError.new("#{self.class}#library must be a library, #{library.inspect} given") unless library.is_a?(Library)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @library = library
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
       6 
13 
     | 
    
         | 
| 
       7 
14 
     | 
    
         
             
                def each
         
     | 
| 
       8 
15 
     | 
    
         
             
                  return unless block_given?
         
     | 
| 
       9 
     | 
    
         
            -
                   
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 16 
     | 
    
         
            +
                  pages_count = nil
         
     | 
| 
      
 17 
     | 
    
         
            +
                  page = 1
         
     | 
| 
      
 18 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    json = JsonDocument.get(library.url(limit: 50, method: 'user.getLovedTracks', page:))
         
     | 
| 
      
 20 
     | 
    
         
            +
                    pages_count = json['lovedtracks']['@attr']['totalPages'].to_i
         
     | 
| 
      
 21 
     | 
    
         
            +
                    json['lovedtracks']['track'].each do |track_json|
         
     | 
| 
      
 22 
     | 
    
         
            +
                      artist = track_json['artist']['name'] || next
         
     | 
| 
      
 23 
     | 
    
         
            +
                      title = track_json['name'] || next
         
     | 
| 
       14 
24 
     | 
    
         
             
                      yield(Track.new(artist:, title:))
         
     | 
| 
       15 
25 
     | 
    
         
             
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                    page += 1
         
     | 
| 
      
 27 
     | 
    
         
            +
                    break if page > pages_count
         
     | 
| 
       16 
28 
     | 
    
         
             
                  end
         
     | 
| 
       17 
29 
     | 
    
         
             
                  nil
         
     | 
| 
       18 
30 
     | 
    
         
             
                end
         
     | 
| 
       19 
31 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                def path
         
     | 
| 
       21 
     | 
    
         
            -
                  'loved'
         
     | 
| 
       22 
     | 
    
         
            -
                end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
32 
     | 
    
         
             
              end
         
     | 
| 
       25 
33 
     | 
    
         | 
| 
       26 
34 
     | 
    
         
             
            end
         
     | 
| 
         @@ -2,51 +2,44 @@ module Notu 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
              class MostPlayedTracks
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
                include  
     | 
| 
      
 5 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
                PERIODS =  
     | 
| 
       8 
     | 
    
         
            -
                  '7 days' => 'LAST_7_DAYS',
         
     | 
| 
       9 
     | 
    
         
            -
                  '30 days' => 'LAST_30_DAYS',
         
     | 
| 
       10 
     | 
    
         
            -
                  '90 days' => 'LAST_90_DAYS',
         
     | 
| 
       11 
     | 
    
         
            -
                  '365 days' => 'LAST_365_DAYS',
         
     | 
| 
       12 
     | 
    
         
            -
                  'Overall' => '',
         
     | 
| 
       13 
     | 
    
         
            -
                }.freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
                PERIODS = %w(overall 7day 1month 3month 6month 12month).freeze
         
     | 
| 
       14 
8 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
                attr_reader :period
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :library, :period
         
     | 
| 
       16 
10 
     | 
    
         | 
| 
       17 
11 
     | 
    
         
             
                def initialize(library, options = {})
         
     | 
| 
       18 
     | 
    
         
            -
                   
     | 
| 
       19 
     | 
    
         
            -
                   
     | 
| 
       20 
     | 
    
         
            -
                   
     | 
| 
      
 12 
     | 
    
         
            +
                  raise ArgumentError.new("#{self.class}#library must be a library, #{library.inspect} given") unless library.is_a?(Library)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @library = library
         
     | 
| 
      
 14 
     | 
    
         
            +
                  options = options.symbolize_keys.reverse_merge(period: PERIODS.first)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  self.period = options[:period]
         
     | 
| 
       21 
16 
     | 
    
         
             
                end
         
     | 
| 
       22 
17 
     | 
    
         | 
| 
       23 
18 
     | 
    
         
             
                def each
         
     | 
| 
       24 
19 
     | 
    
         
             
                  return unless block_given?
         
     | 
| 
       25 
     | 
    
         
            -
                   
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
                  pages_count = nil
         
     | 
| 
      
 21 
     | 
    
         
            +
                  page = 1
         
     | 
| 
      
 22 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 23 
     | 
    
         
            +
                    json = JsonDocument.get(library.url(limit: 50, method: 'user.getTopTracks', page:))
         
     | 
| 
      
 24 
     | 
    
         
            +
                    pages_count = json['toptracks']['@attr']['totalPages'].to_i
         
     | 
| 
      
 25 
     | 
    
         
            +
                    json['toptracks']['track'].each do |track_json|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      artist = track_json['artist']['name'] || next
         
     | 
| 
      
 27 
     | 
    
         
            +
                      title = track_json['name'] || next
         
     | 
| 
      
 28 
     | 
    
         
            +
                      plays_count = track_json['playcount'] || next
         
     | 
| 
       31 
29 
     | 
    
         
             
                      yield(Track.new(artist:, plays_count:, title:))
         
     | 
| 
       32 
30 
     | 
    
         
             
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    page += 1
         
     | 
| 
      
 32 
     | 
    
         
            +
                    break if page > pages_count
         
     | 
| 
       33 
33 
     | 
    
         
             
                  end
         
     | 
| 
       34 
34 
     | 
    
         
             
                  nil
         
     | 
| 
       35 
35 
     | 
    
         
             
                end
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
                def params
         
     | 
| 
       38 
     | 
    
         
            -
                  { 'date_preset' => PERIODS[period] }
         
     | 
| 
       39 
     | 
    
         
            -
                end
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                def path
         
     | 
| 
       42 
     | 
    
         
            -
                  'library/tracks'
         
     | 
| 
       43 
     | 
    
         
            -
                end
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
37 
     | 
    
         
             
                private
         
     | 
| 
       46 
38 
     | 
    
         | 
| 
       47 
39 
     | 
    
         
             
                def period=(value)
         
     | 
| 
       48 
     | 
    
         
            -
                   
     | 
| 
       49 
     | 
    
         
            -
                   
     | 
| 
      
 40 
     | 
    
         
            +
                  string_value = value.to_s
         
     | 
| 
      
 41 
     | 
    
         
            +
                  raise ArgumentError.new("Notu::MostPlayedTracks#period is invalid: #{value.inspect}") unless PERIODS.include?(string_value)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @period = string_value
         
     | 
| 
       50 
43 
     | 
    
         
             
                end
         
     | 
| 
       51 
44 
     | 
    
         | 
| 
       52 
45 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Notu
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class RecentTracks
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :library
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(library)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  raise ArgumentError.new("#{self.class}#library must be a library, #{library.inspect} given") unless library.is_a?(Library)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @library = library
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def each
         
     | 
| 
      
 15 
     | 
    
         
            +
                  return unless block_given?
         
     | 
| 
      
 16 
     | 
    
         
            +
                  pages_count = nil
         
     | 
| 
      
 17 
     | 
    
         
            +
                  page = 1
         
     | 
| 
      
 18 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    json = JsonDocument.get(library.url(limit: 50, method: 'user.getRecentTracks', page:))
         
     | 
| 
      
 20 
     | 
    
         
            +
                    pages_count = json['recenttracks']['@attr']['totalPages'].to_i
         
     | 
| 
      
 21 
     | 
    
         
            +
                    json['recenttracks']['track'].each do |track_json|
         
     | 
| 
      
 22 
     | 
    
         
            +
                      artist = track_json['artist']['#text'] || next
         
     | 
| 
      
 23 
     | 
    
         
            +
                      title = track_json['name'] || next
         
     | 
| 
      
 24 
     | 
    
         
            +
                      yield(Track.new(artist:, title:))
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                    page += 1
         
     | 
| 
      
 27 
     | 
    
         
            +
                    break if page > pages_count
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/notu.rb
    CHANGED
    
    | 
         @@ -3,7 +3,6 @@ require 'active_support/core_ext' 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require 'byebug' if ENV['DEBUGGER']
         
     | 
| 
       4 
4 
     | 
    
         
             
            require 'cgi'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'net/https'
         
     | 
| 
       6 
     | 
    
         
            -
            require 'nokogiri'
         
     | 
| 
       7 
6 
     | 
    
         | 
| 
       8 
7 
     | 
    
         
             
            lib_path = "#{__dir__}/notu"
         
     | 
| 
       9 
8 
     | 
    
         | 
| 
         @@ -18,12 +17,11 @@ require "#{lib_path}/error" 
     | 
|
| 
       18 
17 
     | 
    
         
             
            require "#{lib_path}/network_error"
         
     | 
| 
       19 
18 
     | 
    
         
             
            require "#{lib_path}/parse_error"
         
     | 
| 
       20 
19 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
            require "#{lib_path}/ 
     | 
| 
      
 20 
     | 
    
         
            +
            require "#{lib_path}/api"
         
     | 
| 
       22 
21 
     | 
    
         
             
            require "#{lib_path}/http_download"
         
     | 
| 
      
 22 
     | 
    
         
            +
            require "#{lib_path}/json_document"
         
     | 
| 
       23 
23 
     | 
    
         
             
            require "#{lib_path}/library"
         
     | 
| 
       24 
     | 
    
         
            -
            require "#{lib_path}/listing"
         
     | 
| 
       25 
24 
     | 
    
         
             
            require "#{lib_path}/loved_tracks"
         
     | 
| 
       26 
25 
     | 
    
         
             
            require "#{lib_path}/most_played_tracks"
         
     | 
| 
       27 
     | 
    
         
            -
            require "#{lib_path}/ 
     | 
| 
      
 26 
     | 
    
         
            +
            require "#{lib_path}/recent_tracks"
         
     | 
| 
       28 
27 
     | 
    
         
             
            require "#{lib_path}/track"
         
     | 
| 
       29 
     | 
    
         
            -
            require "#{lib_path}/unknown_username_error"
         
     | 
    
        data/notu.gemspec
    CHANGED
    
    | 
         @@ -16,7 +16,6 @@ Gem::Specification.new do |s| 
     | 
|
| 
       16 
16 
     | 
    
         
             
              s.required_ruby_version = '>= 3.1.0'
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
              s.add_dependency 'activesupport', '>= 7.0.0', '< 8.0.0'
         
     | 
| 
       19 
     | 
    
         
            -
              s.add_dependency 'nokogiri', '>= 1.6.0', '< 1.14.0'
         
     | 
| 
       20 
19 
     | 
    
         | 
| 
       21 
20 
     | 
    
         
             
              s.add_development_dependency 'byebug', '>= 3.2.0', '< 12.0.0'
         
     | 
| 
       22 
21 
     | 
    
         
             
              s.add_development_dependency 'rake', '>= 10.3.0', '< 14.0.0'
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: notu
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version:  
     | 
| 
      
 4 
     | 
    
         
            +
              version: 4.0.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Alexis Toulotte
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2023-01-16 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: activesupport
         
     | 
| 
         @@ -30,26 +30,6 @@ dependencies: 
     | 
|
| 
       30 
30 
     | 
    
         
             
                - - "<"
         
     | 
| 
       31 
31 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       32 
32 
     | 
    
         
             
                    version: 8.0.0
         
     | 
| 
       33 
     | 
    
         
            -
            - !ruby/object:Gem::Dependency
         
     | 
| 
       34 
     | 
    
         
            -
              name: nokogiri
         
     | 
| 
       35 
     | 
    
         
            -
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
       36 
     | 
    
         
            -
                requirements:
         
     | 
| 
       37 
     | 
    
         
            -
                - - ">="
         
     | 
| 
       38 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       39 
     | 
    
         
            -
                    version: 1.6.0
         
     | 
| 
       40 
     | 
    
         
            -
                - - "<"
         
     | 
| 
       41 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       42 
     | 
    
         
            -
                    version: 1.14.0
         
     | 
| 
       43 
     | 
    
         
            -
              type: :runtime
         
     | 
| 
       44 
     | 
    
         
            -
              prerelease: false
         
     | 
| 
       45 
     | 
    
         
            -
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
       46 
     | 
    
         
            -
                requirements:
         
     | 
| 
       47 
     | 
    
         
            -
                - - ">="
         
     | 
| 
       48 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       49 
     | 
    
         
            -
                    version: 1.6.0
         
     | 
| 
       50 
     | 
    
         
            -
                - - "<"
         
     | 
| 
       51 
     | 
    
         
            -
                  - !ruby/object:Gem::Version
         
     | 
| 
       52 
     | 
    
         
            -
                    version: 1.14.0
         
     | 
| 
       53 
33 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       54 
34 
     | 
    
         
             
              name: byebug
         
     | 
| 
       55 
35 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -220,18 +200,17 @@ files: 
     | 
|
| 
       220 
200 
     | 
    
         
             
            - README.mdown
         
     | 
| 
       221 
201 
     | 
    
         
             
            - VERSION
         
     | 
| 
       222 
202 
     | 
    
         
             
            - lib/notu.rb
         
     | 
| 
      
 203 
     | 
    
         
            +
            - lib/notu/api.rb
         
     | 
| 
       223 
204 
     | 
    
         
             
            - lib/notu/error.rb
         
     | 
| 
       224 
     | 
    
         
            -
            - lib/notu/html_document.rb
         
     | 
| 
       225 
205 
     | 
    
         
             
            - lib/notu/http_download.rb
         
     | 
| 
      
 206 
     | 
    
         
            +
            - lib/notu/json_document.rb
         
     | 
| 
       226 
207 
     | 
    
         
             
            - lib/notu/library.rb
         
     | 
| 
       227 
     | 
    
         
            -
            - lib/notu/listing.rb
         
     | 
| 
       228 
208 
     | 
    
         
             
            - lib/notu/loved_tracks.rb
         
     | 
| 
       229 
209 
     | 
    
         
             
            - lib/notu/most_played_tracks.rb
         
     | 
| 
       230 
210 
     | 
    
         
             
            - lib/notu/network_error.rb
         
     | 
| 
       231 
211 
     | 
    
         
             
            - lib/notu/parse_error.rb
         
     | 
| 
       232 
     | 
    
         
            -
            - lib/notu/ 
     | 
| 
      
 212 
     | 
    
         
            +
            - lib/notu/recent_tracks.rb
         
     | 
| 
       233 
213 
     | 
    
         
             
            - lib/notu/track.rb
         
     | 
| 
       234 
     | 
    
         
            -
            - lib/notu/unknown_username_error.rb
         
     | 
| 
       235 
214 
     | 
    
         
             
            - notu.gemspec
         
     | 
| 
       236 
215 
     | 
    
         
             
            homepage: https://github.com/alexistoulotte/notu
         
     | 
| 
       237 
216 
     | 
    
         
             
            licenses:
         
     | 
    
        data/lib/notu/html_document.rb
    DELETED
    
    | 
         @@ -1,19 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Notu
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              module HtmlDocument
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
                def self.get(url, options = {})
         
     | 
| 
       6 
     | 
    
         
            -
                  parse(HttpDownload.get(url, options))
         
     | 
| 
       7 
     | 
    
         
            -
                end
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
                def self.parse(data)
         
     | 
| 
       10 
     | 
    
         
            -
                  data = data.gsub(/ /i, ' ').gsub(/\s+/, ' ')
         
     | 
| 
       11 
     | 
    
         
            -
                  document = Nokogiri::HTML.parse(data, nil, 'UTF-8')
         
     | 
| 
       12 
     | 
    
         
            -
                  raise ParseError.new('Invalid HTML document') if (document / 'head').empty?
         
     | 
| 
       13 
     | 
    
         
            -
                  document
         
     | 
| 
       14 
     | 
    
         
            -
                end
         
     | 
| 
       15 
     | 
    
         
            -
                private_class_method :parse
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
              end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
            end
         
     | 
    
        data/lib/notu/listing.rb
    DELETED
    
    | 
         @@ -1,32 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Notu
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              module Listing
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
                include Enumerable
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                attr_reader :library
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
                def initialize(library)
         
     | 
| 
       10 
     | 
    
         
            -
                  raise ArgumentError.new("#{self.class}#library must be a library, #{library.inspect} given") unless library.is_a?(Library)
         
     | 
| 
       11 
     | 
    
         
            -
                  @library = library
         
     | 
| 
       12 
     | 
    
         
            -
                end
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                def page_urls
         
     | 
| 
       15 
     | 
    
         
            -
                  (1..pages_count).map do |index|
         
     | 
| 
       16 
     | 
    
         
            -
                    library.url(path:, query: params.merge('page' => index))
         
     | 
| 
       17 
     | 
    
         
            -
                  end
         
     | 
| 
       18 
     | 
    
         
            -
                end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                def pages_count
         
     | 
| 
       21 
     | 
    
         
            -
                  document = HtmlDocument.get(library.url(path:, query: params))
         
     | 
| 
       22 
     | 
    
         
            -
                  [1, (document / 'ul.pagination-list li.pagination-page').text.split(/\s+/).map(&:to_i)].flatten.compact.max
         
     | 
| 
       23 
     | 
    
         
            -
                end
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                def params
         
     | 
| 
       26 
     | 
    
         
            -
                  # to be overriden
         
     | 
| 
       27 
     | 
    
         
            -
                  {}
         
     | 
| 
       28 
     | 
    
         
            -
                end
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
              end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
            end
         
     | 
    
        data/lib/notu/played_tracks.rb
    DELETED
    
    | 
         @@ -1,26 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Notu
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              class PlayedTracks
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
                include Listing
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                def each
         
     | 
| 
       8 
     | 
    
         
            -
                  return unless block_given?
         
     | 
| 
       9 
     | 
    
         
            -
                  page_urls.each do |url|
         
     | 
| 
       10 
     | 
    
         
            -
                    document = HtmlDocument.get(url)
         
     | 
| 
       11 
     | 
    
         
            -
                    (document / 'table.chartlist tbody tr').each do |element|
         
     | 
| 
       12 
     | 
    
         
            -
                      artist = (element / 'td.chartlist-artist a').first.try(:text) || next
         
     | 
| 
       13 
     | 
    
         
            -
                      title = (element / 'td.chartlist-name a').first.try(:text) || next
         
     | 
| 
       14 
     | 
    
         
            -
                      yield(Track.new(artist:, title:))
         
     | 
| 
       15 
     | 
    
         
            -
                    end
         
     | 
| 
       16 
     | 
    
         
            -
                  end
         
     | 
| 
       17 
     | 
    
         
            -
                  nil
         
     | 
| 
       18 
     | 
    
         
            -
                end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                def path
         
     | 
| 
       21 
     | 
    
         
            -
                  'library'
         
     | 
| 
       22 
     | 
    
         
            -
                end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
              end
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
            end
         
     |