apple_music_client 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9d166b694f4a2075905d1060763fea4b8d6c2d922505364b5bc0ca9a81d4dbd9
4
+ data.tar.gz: c7baf1770de42a4d6655f34407e2eee3e6611e0a02efa016dbf55632aabf0c12
5
+ SHA512:
6
+ metadata.gz: b5c2f7ad3442bd16f0f9541f4e6fbea51ac6e2a2d3be8b7ed56ae67d928ebd85abcca1c2beae8d6761836775ea3c1ef1eba58ff7bd9c1fdd637ca588f6675a3c
7
+ data.tar.gz: 81e2be6832ee559eca83fa0a080a1b8fd2849ae93161888f4e0b852526a7a204a0a263f04ef783f3ae8959e1bf56f90de0b37527880e699ed8c80266139e74de
@@ -0,0 +1,2 @@
1
+ require_relative './storeClient'
2
+ require_relative './libraryClient'
data/lib/client.rb ADDED
@@ -0,0 +1,92 @@
1
+ require 'jwt'
2
+ require 'httparty'
3
+ require 'time'
4
+
5
+ module AppleMusic
6
+
7
+ # THANKS https://medium.com/@defv/connecting-to-the-apple-music-api-from-a-ruby-on-rails-application-eba9d12f5cf9
8
+ class TokenFactory
9
+
10
+ def self.generate(secret_key_path:, team_id:, key_id:)
11
+ ecdsa_key = OpenSSL::PKey::EC.new File.read(secret_key_path)
12
+ ecdsa_public = OpenSSL::PKey::EC.new ecdsa_key
13
+ ecdsa_public.private_key = nil
14
+ JWT.encode TokenFactory.authentication_payload(team_id), ecdsa_public, 'ES256', { kid: key_id }
15
+ end
16
+
17
+ private
18
+
19
+ def self.authentication_payload(team_id)
20
+ {
21
+ iss: team_id,
22
+ iat: Time.now.to_i - 100,
23
+ exp: Time.now.to_i + 12000
24
+ }
25
+ end
26
+
27
+ end
28
+
29
+ class Client
30
+
31
+ def initialize(token)
32
+ @token = token
33
+ end
34
+
35
+ def get(resource)
36
+ response = HTTParty.get(
37
+ "https://api.music.apple.com#{resource}",
38
+ {headers: headers})
39
+
40
+ if response.code == 200
41
+ JSON.parse(response.body)
42
+ else
43
+ puts "NON 200 CODE for resource #{resource}"
44
+ puts response
45
+ end
46
+ end
47
+
48
+ def post(resource)
49
+ HTTParty.post(
50
+ "https://api.music.apple.com#{resource}",
51
+ {headers: headers}
52
+ )
53
+ end
54
+
55
+ def headers
56
+ {
57
+ 'Authorization': "Bearer #{@token}"
58
+ }
59
+ end
60
+
61
+ end
62
+
63
+ class PaginatedResponse
64
+ include Enumerable
65
+
66
+ def initialize(client, response)
67
+ @client = client
68
+ @response = response
69
+ end
70
+
71
+ def each(&block)
72
+ return to_enum(:each) unless block_given?
73
+ return if @response.nil? or @response["data"].nil?
74
+
75
+ @response["data"].each(&block)
76
+ return if @response["next"].nil?
77
+ PaginatedResponse.new(@client, @client.get(@response["next"])).each(&block)
78
+ end
79
+
80
+ end
81
+
82
+
83
+ class DataType < Struct
84
+ def initialize(args)
85
+ args.merge(args['attributes'])
86
+ .filter { |k,_| members.include?(k.to_sym) }
87
+ .each { |k,v| public_send("#{k}=", v) }
88
+ freeze
89
+ end
90
+ end
91
+
92
+ end
@@ -0,0 +1,26 @@
1
+ require_relative './client'
2
+
3
+ module AppleMusic
4
+
5
+ class LibraryClient < Client
6
+
7
+ def initialize(token, user_token)
8
+ super(token)
9
+ @user_token = user_token
10
+ end
11
+
12
+ def get_user_artists
13
+ PaginatedResponse.new(self, get("/v1/me/library/artists"))
14
+ end
15
+
16
+ def add_to_library(album:)
17
+ post("/v1/me/library?ids[albums]=#{album}")
18
+ end
19
+
20
+ def headers
21
+ super.merge({ 'Music-User-Token': @user_token })
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,54 @@
1
+ require 'erb'
2
+ require 'json'
3
+ require 'date'
4
+ require_relative './client'
5
+
6
+ module AppleMusic
7
+
8
+ class StoreClient < Client
9
+
10
+ def find_artist(artist_name:)
11
+ response = get_catalog("search?term=#{escape(artist_name)}&types=artists")
12
+ parse(response.dig("results", "artists", "data"))[0]
13
+ end
14
+
15
+ def get_artist(artist_id:)
16
+ response = get_catalog("artists/#{artist_id}")
17
+ parse(response["data"])[0]
18
+ end
19
+
20
+ def get_albums(artist:)
21
+ response = PaginatedResponse.new(self, get("/v1/catalog/us/artists/#{artist.id}/albums?limit=100"))
22
+ parse(response).sort_by { |album| album.releaseDate }.reverse
23
+ end
24
+
25
+ private
26
+
27
+ def escape(term)
28
+ ERB::Util.url_encode(term)
29
+ end
30
+
31
+ def get_catalog(resource)
32
+ get("/v1/catalog/us/#{resource}")
33
+ end
34
+
35
+ def parse(payload)
36
+ return [] if payload.nil?
37
+
38
+ payload.map do |value|
39
+ if value["type"] == "artists"
40
+ Artist.new(value)
41
+ elsif value["type"] == "albums"
42
+ Album.new(value)
43
+ else
44
+ puts "Unknown type:", value
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Artist = DataType.new(:id, :name)
51
+ Album = DataType.new(:id, :name, :isSingle, :releaseDate)
52
+
53
+
54
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apple_music_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kaeden Wile
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-05-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/apple_music_client.rb
20
+ - lib/client.rb
21
+ - lib/libraryClient.rb
22
+ - lib/storeClient.rb
23
+ homepage: https://rubygems.org/gems/apple_music_client
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubygems_version: 3.1.4
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: Client for access to Apple Music APIs
46
+ test_files: []