Class: VkMusic::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/vk_music/client.rb

Overview

Main class with all the interface. To start working with VK audios firstly create new client with Client.new.

Instance Attribute Summary collapse

Loading audios collapse

Other collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Client

Create new client and login.

Parameters:

  • options (Hash) (defaults to: {})

    hash with options.

Options Hash (options):

  • :username (String)

    usually telephone number or email.

  • :password (String)

Raises:

  • (ArgumentError)


38
39
40
41
42
43
44
45
46
47
# File 'lib/vk_music/client.rb', line 38

def initialize(options = {})
  # Arguments check
  raise ArgumentError, "Options hash must be provided", caller unless options.class == Hash
  raise ArgumentError, "Username is not provided", caller unless options.has_key?(:username)
  raise ArgumentError, "Password is not provided", caller unless options.has_key?(:password)
  
  # Setting up client
  @agent = Mechanize.new
  (options[:username], options[:password])
end

Instance Attribute Details

#idInteger (readonly)

Returns ID of client.

Returns:

  • (Integer)

    ID of client.



23
24
25
# File 'lib/vk_music/client.rb', line 23

def id
  @id
end

#nameString (readonly)

Returns name of client.

Returns:

  • (String)

    name of client.



27
28
29
# File 'lib/vk_music/client.rb', line 27

def name
  @name
end

Instance Method Details

#attached_audios_amount(url) ⇒ Integer #attached_audios_amount(options) ⇒ Integer

Get amount of audios attached to specified post.

Overloads:

  • #attached_audios_amount(url) ⇒ Integer

    Parameters:

    • url (String)

      URL to post.

  • #attached_audios_amount(options) ⇒ Integer

    Parameters:

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :owner_id (Integer)

      numerical ID of wall owner.

    • :post_id (Integer)

      numerical ID of post.

Returns:

  • (Integer)

    amount of audios.

Raises:



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
# File 'lib/vk_music/client.rb', line 448

def attached_audios_amount(arg)
  begin
    case arg
      when String
        owner_id, post_id = arg.match(Constants::Regex::VK_WALL_URL_POSTFIX).captures
      when Hash
        options = arg
        owner_id = options[:owner_id].to_i
        post_id = options[:post_id].to_i
      else
        raise
    end
  rescue
    raise ArgumentError, "Bad arguments", caller
  end

  url = "#{Constants::URL::VK[:wall]}#{owner_id}_#{post_id}"
  begin
    page = load__page(url)
  rescue Exceptions::RequestError => error
    raise Exceptions::ParseError, "Failed request: #{error.message}", caller
  end

  raise Exceptions::ParseError, "Post not found: #{owner_id}_#{post_id}", caller unless page.css(".service_msg_error").empty?
  begin
    result = page.css(".wi_body > .pi_medias .medias_audio").size
  rescue Exception => error
    raise Exceptions::ParseError, "Unable to get amount of audios in post #{owner_id}_#{post_id}. Error: #{error.message}", caller
  end
  result
end

#audios(url, options) ⇒ Playlist #audios(options) ⇒ Playlist

Note:

currently this method is only able to load 100 audios with download URL.

Get user or group audios.

Overloads:

  • #audios(url, options) ⇒ Playlist

    Parameters:

    • url (String)

      URL to user/group page or audios.

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :up_to (Integer) — default: MAXIMUM_PLAYLIST_SIZE

      maximum amount of audios to load. If 0, no audios would be loaded (Just information about playlist). If less than 0, will load whole playlist.

  • #audios(options) ⇒ Playlist

    Parameters:

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :owner_id (Integer)

      numerical ID of owner.

    • :up_to (Integer) — default: MAXIMUM_PLAYLIST_SIZE

      maximum amount of audios to load. If 0, no audios would be loaded (Just information about playlist). If less than 0, will load whole playlist.

Parameters:

  • options (Hash)

    a customizable set of options

Returns:

  • (Playlist)

    playlist with audios. Possibly empty. Possibly contains audios without download URL.



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/vk_music/client.rb', line 189

def audios(*args)
  begin
    case
      when (args.size == 1 && String === args[0] ) ||
           (args.size == 2 && String === args[0] && Hash === args[1])
        owner_id = page_id(args[0].to_s)
        options = args[1] || {}
      when args.size == 1 && Hash === args[0]
        owner_id = args[0][:owner_id].to_i
        options = args[0]
      else
        raise
    end
  rescue
    raise ArgumentError, "Bad arguments", caller
  end

  options[:up_to]    ||= Constants::MAXIMUM_PLAYLIST_SIZE

  playlist__json(owner_id, -1, nil, options)
end

#find(query, options) ⇒ Array<Audio>, Array<Playlist> #find(options) ⇒ Array<Audio>, Array<Playlist> Also known as: search

TODO:

search in group audios.

Note:

some audios and playlists might be removed from search.

Search for audio or playlist.

Possible values of type option:

  • :audio - search for audios. Returns up to 50 audios.

  • :playlist - search for playlists. Returns up to 6 playlists without audios (Loaded with up_to: 0 option). You can get all the audios of selected playlist calling #playlist method with gained info.

Overloads:

  • #find(query, options) ⇒ Array<Audio>, Array<Playlist>

    Parameters:

    • query (String)

      string to search for.

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :type (Symbol) — default: :audio

      what to search for (you can find available values for this option above).

  • #find(options) ⇒ Array<Audio>, Array<Playlist>

    Parameters:

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :query (String)

      string to search for.

    • :type (Symbol) — default: :audio

      what to search for (you can find available values for this option above).

Parameters:

  • options (Hash)

    a customizable set of options

Returns:

  • (Array<Audio>, Array<Playlist>)

    array with audios or playlists matching given string. Possibly empty. Possibly contains audios or playlists without download URL.



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
# File 'lib/vk_music/client.rb', line 79

def find(*args)
  begin
    case
      when (args.size == 1 && String === args[0]) ||
           (args.size == 2 && String === args[0] && Hash === args[1])
        options = args[1] || {}
        query = args[0]
      when args.size == 1 && Hash === args[0]
        options = args[0]
        query = options[:query].to_s
      else
        raise
    end
  rescue
    raise ArgumentError, "Bad arguments", caller
  end

  options[:type] ||= :audio

  uri = URI(Constants::URL::VK[:audios])

  case options[:type]
    when :audio
      uri.query = Utility.hash_to_params({ "act" => "search", "q" => query })
      audios__from_page(uri)
    when :playlist
      uri.query = Utility.hash_to_params({ "q" => query, "tab" => "global" })
      urls = playlist_urls__from_page(uri)
      urls.map { |url| playlist(url, up_to: 0, with_url: false) }
    else
      raise ArgumentError, "Bad :type option", caller
  end
end

#from_id(args) ⇒ Array<Audio>

TODO:

workaround for not unique audios in request

Note:

warning: audios must not match.

Get audios with download URLs by their IDs and secrets.

Parameters:

  • args (Array<Audio, Array<(owner_id, audio_id, secret_1, secret_2)>, "#{owner_id}_#{id}_#{secret_1}_#{secret_2}">)

Returns:

  • (Array<Audio>)

    array of audios with download URLs.



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
# File 'lib/vk_music/client.rb', line 309

def from_id(args)
  begin
    args.map! do |el| 
      case el
        when Array
          el.join("_")
        when Audio
          "#{el.owner_id}_#{el.id}_#{el.secret_1}_#{el.secret_2}"
        when String
          el # Do not change
        else
          raise
      end
    end
  rescue
    raise ArgumentError, "Bad arguments", caller
  end
  
  result = []
  args.each_slice(10) do |subarray|
    json = load__json__audios_by_id(subarray)
    subresult = audios__from_data(json["data"][0].to_a)
    raise Exceptions::ParseError, "Result size don't match: excepected #{subarray.size}, got #{subresult.size}", caller if subresult.size != subarray.size
    result.concat(subresult)
  end
  result
end

#last_post_id(url) ⇒ Integer? #last_post_id(owner_id) ⇒ Integer?

Note:

requesting for “vk.com/id0” will raise ArgumentError. Use client.last_post_id(owner_id: client.id) to get last post of client.

Get ID of last post.

Overloads:

  • #last_post_id(url) ⇒ Integer?

    Parameters:

    • url (String)

      URL to wall owner.

  • #last_post_id(owner_id) ⇒ Integer?

    Parameters:

    • owner_id (Integer)

      numerical ID of wall owner.

Returns:

  • (Integer, nil)

    ID of last post or nil if there are no posts.

Raises:

  • (ArgumentError)


397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# File 'lib/vk_music/client.rb', line 397

def last_post_id(arg)
  begin
    case arg
      when String
        path = arg.match(Constants::Regex::VK_URL)[1]
      when Integer
        owner_id = arg
        path = "#{owner_id < 0 ? "club" : "id"}#{owner_id.abs}"
      else
        raise
    end
  rescue
    raise ArgumentError, "Bad arguments", caller
  end
  raise ArgumentError, "Requesting this method for id0 is forbidden", caller if path == "id0"

  url = "#{Constants::URL::VK[:home]}/#{path}"

  begin
    page = load__page(url)
  rescue Exceptions::RequestError => error
    raise Exceptions::ParseError, "Failed request: #{error.message}", caller
  end

  # Ensure this isn't some random vk page
  raise Exceptions::ParseError, "Page at #{url} doesn't seem to be a group or user page", caller unless page.at_css(".PageBlock .owner_panel")

  begin
    posts = page.css(".wall_posts > .wall_item .post__anchor")
    posts_ids = posts.map do |post|
      post ? post.attribute("name").to_s.match(Constants::Regex::VK_POST_URL_POSTFIX)[2].to_i : 0
    end
    # To avoid checking id of pinned post need to take maximum id.
    return posts_ids.max
  rescue Exception => error
    raise Exceptions::ParseError, "Unable to get last post on #{url}. Error: #{error.message}", caller
  end
end

#page_id(str) ⇒ Integer

Get user or group ID. Sends one request if custom ID provided

Parameters:

  • str (String)

    link, ID with/without prefix or custom ID.

Returns:

  • (Integer)

    page ID.

Raises:

  • (ArgumentError)


349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/vk_music/client.rb', line 349

def page_id(str)
  raise ArgumentError, "Bad arguments", caller unless str.class == String

  case str
    when Constants::Regex::VK_URL
      path = str.match(Constants::Regex::VK_URL)[1]
      id = page_id(path) # Recursive call
    when Constants::Regex::VK_ID_STR
      id = str.to_i
    when Constants::Regex::VK_AUDIOS_URL_POSTFIX
      id = str.match(/-?\d+/).to_s.to_i # Numbers with sign
    when Constants::Regex::VK_PREFIXED_ID_STR
      id = str.match(/\d+/).to_s.to_i # Just numbers. Sign needed
      id *= -1 unless str.start_with?("id")
    when Constants::Regex::VK_CUSTOM_ID
      url = "#{Constants::URL::VK[:home]}/#{str}"
      begin
        page = load__page(url)
      rescue Exceptions::RequestError => error
        raise Exceptions::ParseError, "Failed request: #{error.message}", caller
      end          
      
      raise Exceptions::ParseError, "Page #{str} doesn't seem to be a group or user page", caller unless page.at_css(".PageBlock .owner_panel")
      
      begin
        id = page.link_with(href: Constants::Regex::VK_HREF_ID_CONTAINING).href.slice(Constants::Regex::VK_ID).to_i # Numbers with sign
      rescue Exception => error
        raise Exceptions::ParseError, "Unable to get user or group ID. Custom ID: #{str}. Error: #{error.message}", caller
      end
    else
      raise Exceptions::ParseError, "Unable to convert \"#{str}\" into ID", caller
  end
  id
end

#playlist(url, options) ⇒ Playlist #playlist(options) ⇒ Playlist

Get VK playlist.

Overloads:

  • #playlist(url, options) ⇒ Playlist

    Parameters:

    • url (String)

      URL to playlist.

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :up_to (Integer) — default: MAXIMUM_PLAYLIST_SIZE

      maximum amount of audios to load. If 0, no audios would be loaded (Just information about playlist). If less than 0, will load whole playlist.

    • :with_url (Boolean) — default: true

      makes all the audios have download URLs, but every 100 audios will cost one more request. You can reduce amount of requests using option up_to. Otherwise audio download URL would be accessable only with #from_id. Main advantage of disabling URLs is the fact that 2000 audios will be loaded per request, which is 20 times more effecient.

  • #playlist(options) ⇒ Playlist

    Use options owner_id, playlist_id and access_hash instead of URL.

    Parameters:

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :owner_id (Integer)

      playlist owner ID.

    • :playlist_id (Integer)

      ID of the playlist.

    • :access_hash (String)

      access hash to playlist. Might not exist.

    • :up_to (Integer) — default: MAXIMUM_PLAYLIST_SIZE

      maximum amount of audios to load. If 0, no audios would be loaded (Just information about playlist). If less than 0, will load whole playlist.

    • :with_url (Boolean) — default: true

      makes all the audios have download URLs, but every 100 audios will cost one more request. You can reduce amount of requests using option up_to. Otherwise audio download URL would be accessable only with #from_id. Main advantage of disabling URLs is the fact that 2000 audios will be loaded per request, which is 20 times more effecient.

Parameters:

  • options (Hash)

    a customizable set of options

Returns:

  • (Playlist)

    playlist with audios. Possibly empty. Possibly contains audios without download URL.



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/vk_music/client.rb', line 141

def playlist(*args)
  begin
    case
      when (args.size == 1 && String === args[0]) ||
           (args.size == 2 && String === args[0] && Hash === args[1])
        options = args[1] || {}
        owner_id, playlist_id, access_hash = args[0].to_s.match(Constants::Regex::VK_PLAYLIST_URL_POSTFIX).captures
      when args.size == 1 && Hash === args[0]
        options = args[0]
        owner_id, playlist_id, access_hash = options[:owner_id].to_i, options[:playlist_id].to_i, options[:access_hash].to_s
      else
        raise
    end
  rescue
    raise ArgumentError, "Bad arguments", caller
  end
  
  options[:up_to] ||= Constants::MAXIMUM_PLAYLIST_SIZE
  options[:with_url] = true if options[:with_url].nil?

  if options[:with_url]
    playlist__web(owner_id, playlist_id, access_hash, options)
  else
    playlist__json(owner_id, playlist_id, access_hash, options)
  end
end

#post(url) ⇒ Array<Audio> #post(options) ⇒ Array<Audio>

Get audios attached to post.

Overloads:

  • #post(url) ⇒ Array<Audio>

    Parameters:

    • url (String)

      URL to post.

  • #post(options) ⇒ Array<Audio>

    Parameters:

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :owner_id (Integer)

      numerical ID of wall owner.

    • :post_id (Integer)

      numerical ID of post.

Returns:

  • (Array<Audio>)

    audios with download URLs.



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/vk_music/client.rb', line 279

def post(arg)
  begin
    case arg
      when String
        owner_id, post_id = arg.match(Constants::Regex::VK_WALL_URL_POSTFIX).captures
      when Hash
        options = arg
        owner_id = options[:owner_id].to_i
        post_id = options[:post_id].to_i
      else
        raise
    end
  rescue
    raise ArgumentError, "Bad arguments", caller
  end

  amount = attached_audios_amount(owner_id: owner_id, post_id: post_id)
  wall(owner_id: owner_id, post_id: post_id, up_to: amount)
end

#wall(url, options) ⇒ Array<Audio> #wall(options) ⇒ Array<Audio>

Note:

this method is only able to load up to 91 audios from wall.

Get audios on wall of user or group starting with given post.

Overloads:

  • #wall(url, options) ⇒ Array<Audio>

    Load last audios from wall.

    Parameters:

    • url (String)

      URL to user/group page.

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :with_url (Boolean) — default: true

      automatically use #from_id to get download URLs.

  • #wall(options) ⇒ Array<Audio>

    Load audios starting from some exact post.

    Parameters:

    • options (Hash)

      hash with options.

    Options Hash (options):

    • :owner_id (Integer)

      numerical ID of wall owner.

    • :post_id (Integer)

      numerical ID of post.

    • :with_url (Boolean) — default: true

      automatically use #from_id to get download URLs.

Parameters:

  • up_to (Hash)

    a customizable set of options

  • options (Hash)

    a customizable set of options

Returns:

  • (Array<Audio>)

    array of audios from wall. Possibly empty.



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/vk_music/client.rb', line 238

def wall(*args)
  begin
    case
      when (args.size == 1 && args[0].class == String) ||
           (args.size == 2 && args[0].class == String && args[1].class == Hash)
        url = args[0].to_s
        owner_id = page_id(url)
        post_id = last_post_id(owner_id)
        options = args[1] || {}
        return [] if post_id.nil?
      when args.length == 1 && Hash === args[0]
        options = args[0]
        owner_id = options[:owner_id].to_i
        post_id = options[:post_id].to_i
      else
        raise
    end
  rescue Exceptions::ParseError => error
    raise Exceptions::ParseError, "Unable to get last post id. Error: #{error.message}", caller
  rescue
    raise ArgumentError, "Bad arguments", caller
  end

  options[:up_to] ||= 10
  options[:with_url] = true if options[:with_url].nil?

  wall__json(owner_id, post_id, options)
end