kagu 2.0.1 → 2.0.2
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/README.mdown +6 -1
- data/VERSION +1 -1
- data/kagu.gemspec +2 -2
- data/lib/kagu/finder.rb +1 -1
- data/lib/kagu/playlist.rb +11 -11
- data/lib/kagu/playlists.rb +2 -2
- data/lib/kagu/track.rb +24 -24
- data/lib/kagu/tracks.rb +3 -3
- metadata +5 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0334dfd2cbbf21419dd63838d1f1c2ddf33799086aeb6c4f424f641fb848366
|
4
|
+
data.tar.gz: 9a20fd6dcb1014b70c1e5819ecda2d1134e69e69749269437a59685b67c2e451
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f72d388cb967ea25ef360c378036956f3b7566c393614688733a1fd4316ed6b9f68928df97539df74f494e5ae2fcb5160e2a9bff60a6af0b9a0d8532cdb9d85d
|
7
|
+
data.tar.gz: 9f405adb7ed3da432c01d5466666326ac34de34bb796d3525699bf8cc93806c8fe60ad530ec849c85136bb67a6eca815ad089be09b0f2c8d486cc80e12aa7b2c
|
data/README.mdown
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# Kagu
|
2
2
|
|
3
|
-
Ruby API to manage
|
3
|
+
Ruby API to manage macOS Music tracks and playlists.
|
4
|
+
|
5
|
+
**Important note for macOS Catalina (10.15) users**: Apple dropped automatic
|
6
|
+
XML library export you need to manually export your XML library to
|
7
|
+
`$HOME/Music/iTunes/iTunes Music Library.xml` path to make `kagu` work
|
8
|
+
properly.
|
4
9
|
|
5
10
|
## Installation
|
6
11
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.
|
1
|
+
2.0.2
|
data/kagu.gemspec
CHANGED
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.author = 'Alexis Toulotte'
|
6
6
|
s.email = 'al@alweb.org'
|
7
7
|
s.homepage = 'https://github.com/alexistoulotte/kagu'
|
8
|
-
s.summary = 'API for
|
9
|
-
s.description = 'API to manage
|
8
|
+
s.summary = 'API for macOS Music'
|
9
|
+
s.description = 'API to manage macOS Music tracks and playlists'
|
10
10
|
s.license = 'MIT'
|
11
11
|
|
12
12
|
s.files = `git ls-files | grep -vE '^(spec/|test/|\\.|Gemfile|Rakefile)'`.split("\n")
|
data/lib/kagu/finder.rb
CHANGED
@@ -116,7 +116,7 @@ module Kagu
|
|
116
116
|
def tracks
|
117
117
|
return @tracks if @tracks
|
118
118
|
(@tracks = library.tracks.to_a).tap do |tracks|
|
119
|
-
Kagu.logger.debug('Kagu') { "Loaded #{tracks.size} track(s) from
|
119
|
+
Kagu.logger.debug('Kagu') { "Loaded #{tracks.size} track(s) from library" }
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
data/lib/kagu/playlist.rb
CHANGED
@@ -28,10 +28,10 @@ module Kagu
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def add_tracks
|
31
|
-
Kagu.logger.info('Kagu') { "Adding #{tracks.size} track(s) to
|
31
|
+
Kagu.logger.info('Kagu') { "Adding #{tracks.size} track(s) to playlist #{name.inspect}" }
|
32
32
|
tracks.map(&:id).each_slice(500) do |ids|
|
33
33
|
AppleScript.execute(%Q{
|
34
|
-
tell application "
|
34
|
+
tell application "Music"
|
35
35
|
set playlistToPush to user playlist #{name.inspect}
|
36
36
|
set idsToAdd to {#{ids.join(',')}}
|
37
37
|
repeat with idToAdd in idsToAdd
|
@@ -46,9 +46,9 @@ module Kagu
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def clear
|
49
|
-
Kagu.logger.info('Kagu') { "Removing all tracks from
|
49
|
+
Kagu.logger.info('Kagu') { "Removing all tracks from playlist #{name.inspect}" }
|
50
50
|
AppleScript.execute(%Q{
|
51
|
-
tell application "
|
51
|
+
tell application "Music"
|
52
52
|
delete tracks of playlist #{name.inspect}
|
53
53
|
end tell
|
54
54
|
})
|
@@ -58,9 +58,9 @@ module Kagu
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def create
|
61
|
-
Kagu.logger.info('Kagu') { "Creating
|
61
|
+
Kagu.logger.info('Kagu') { "Creating playlist #{name.inspect}" }
|
62
62
|
AppleScript.execute(%Q{
|
63
|
-
tell application "
|
63
|
+
tell application "Music"
|
64
64
|
if not (exists user playlist #{name.inspect}) then
|
65
65
|
make new user playlist with properties { name: #{name.inspect} }
|
66
66
|
end if
|
@@ -71,11 +71,6 @@ module Kagu
|
|
71
71
|
raise Error.new(e)
|
72
72
|
end
|
73
73
|
|
74
|
-
def itunes_name=(value)
|
75
|
-
@@html_entities ||= HTMLEntities.new
|
76
|
-
self.name = @@html_entities.decode(value)
|
77
|
-
end
|
78
|
-
|
79
74
|
def name=(value)
|
80
75
|
@name = value.to_s.squish.presence
|
81
76
|
end
|
@@ -84,6 +79,11 @@ module Kagu
|
|
84
79
|
@tracks = [values].flatten.select { |value| value.is_a?(Track) }
|
85
80
|
end
|
86
81
|
|
82
|
+
def xml_name=(value)
|
83
|
+
@@html_entities ||= HTMLEntities.new
|
84
|
+
self.name = @@html_entities.decode(value)
|
85
|
+
end
|
86
|
+
|
87
87
|
end
|
88
88
|
|
89
89
|
end
|
data/lib/kagu/playlists.rb
CHANGED
@@ -24,7 +24,7 @@ module Kagu
|
|
24
24
|
tracks = {}.tap do |tracks|
|
25
25
|
library.tracks.each { |track| tracks[track.id] = track }
|
26
26
|
end
|
27
|
-
Kagu.logger.debug('Kagu') { "Reading
|
27
|
+
Kagu.logger.debug('Kagu') { "Reading library playlists from #{library.path.inspect}" }
|
28
28
|
File.open(library.path, 'r') do |file|
|
29
29
|
begin
|
30
30
|
line = file.readline.strip
|
@@ -39,7 +39,7 @@ module Kagu
|
|
39
39
|
next
|
40
40
|
end
|
41
41
|
if line == '</array>'
|
42
|
-
yield(Playlist.new(
|
42
|
+
yield(Playlist.new(tracks: playlist_tracks, xml_name: playlist_name)) if playlist_name.present? && playlist_tracks.any?
|
43
43
|
playlist_name = nil
|
44
44
|
playlist_tracks = []
|
45
45
|
next
|
data/lib/kagu/track.rb
CHANGED
@@ -74,62 +74,62 @@ module Kagu
|
|
74
74
|
@id = value.to_s =~ /\A[0-9]+\z/ ? value.to_i : nil
|
75
75
|
end
|
76
76
|
|
77
|
-
def
|
77
|
+
def length=(value)
|
78
|
+
@length = value.to_s =~ /\A[0-9]+\z/ ? value.to_i : nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def path=(value)
|
82
|
+
@path = value.to_s.presence
|
83
|
+
raise Error.new("No such file: #{path.inspect}") if File.exists?(path) && !exists?
|
84
|
+
Kagu.logger.error('Kagu') { "No such track: #{path.inspect}" } unless exists?
|
85
|
+
end
|
86
|
+
|
87
|
+
def title=(value)
|
88
|
+
@title = value.to_s.squish.presence
|
89
|
+
end
|
90
|
+
|
91
|
+
def xml_album=(value)
|
78
92
|
self.album = html_entities_decode(value)
|
79
93
|
end
|
80
94
|
|
81
|
-
def
|
95
|
+
def xml_artist=(value)
|
82
96
|
self.artist = html_entities_decode(value)
|
83
97
|
end
|
84
98
|
|
85
|
-
def
|
99
|
+
def xml_bpm=(value)
|
86
100
|
self.bpm = value
|
87
101
|
end
|
88
102
|
|
89
|
-
def
|
103
|
+
def xml_date_added=(value)
|
90
104
|
self.added_at = value.present? ? Time.parse(value.to_s) : nil
|
91
105
|
end
|
92
106
|
|
93
|
-
def
|
107
|
+
def xml_genre=(value)
|
94
108
|
self.genre = html_entities_decode(value)
|
95
109
|
end
|
96
110
|
|
97
|
-
def
|
111
|
+
def xml_location=(value)
|
98
112
|
path = CGI.unescape(html_entities_decode(value).gsub('+', '%2B')).gsub(/\Afile:\/\/(localhost)?/, '')
|
99
113
|
path = path.encode('UTF-8', 'UTF-8-MAC') if IS_MAC_OS
|
100
114
|
self.path = path
|
101
115
|
end
|
102
116
|
|
103
|
-
def
|
117
|
+
def xml_name=(value)
|
104
118
|
self.title = html_entities_decode(value)
|
105
119
|
end
|
106
120
|
|
107
|
-
def
|
121
|
+
def xml_total_time=(value)
|
108
122
|
self.length = value.to_s =~ /\A[0-9]+\z/ ? (value.to_i / 1000.0).round : nil
|
109
123
|
end
|
110
124
|
|
111
|
-
def
|
125
|
+
def xml_track_id=(value)
|
112
126
|
self.id = value
|
113
127
|
end
|
114
128
|
|
115
|
-
def
|
129
|
+
def xml_year=(value)
|
116
130
|
self.year = value
|
117
131
|
end
|
118
132
|
|
119
|
-
def length=(value)
|
120
|
-
@length = value.to_s =~ /\A[0-9]+\z/ ? value.to_i : nil
|
121
|
-
end
|
122
|
-
|
123
|
-
def path=(value)
|
124
|
-
@path = value.to_s.presence
|
125
|
-
raise Error.new("No such file: #{path.inspect}") if File.exists?(path) && !exists?
|
126
|
-
Kagu.logger.error('Kagu') { "No such iTunes track: #{path.inspect}" } unless exists?
|
127
|
-
end
|
128
|
-
|
129
|
-
def title=(value)
|
130
|
-
@title = value.to_s.squish.presence
|
131
|
-
end
|
132
|
-
|
133
133
|
def year=(value)
|
134
134
|
@year = value.to_s =~ /\A\d{,4}\z/ ? value.to_i : nil
|
135
135
|
end
|
data/lib/kagu/tracks.rb
CHANGED
@@ -15,7 +15,7 @@ module Kagu
|
|
15
15
|
|
16
16
|
def each(&block)
|
17
17
|
return unless block_given?
|
18
|
-
Kagu.logger.debug('Kagu') { "Loading
|
18
|
+
Kagu.logger.debug('Kagu') { "Loading library tracks from #{library.path.inspect}" }
|
19
19
|
File.open(library.path, 'r') do |file|
|
20
20
|
while !file.eof? && (line = file.readline.strip)
|
21
21
|
next unless line.starts_with?('<key>Track ID</key>')
|
@@ -23,11 +23,11 @@ module Kagu
|
|
23
23
|
begin
|
24
24
|
match = line.match(/<key>(.+)<\/key><(\w+)>(.*)<\/\2>/)
|
25
25
|
next unless match
|
26
|
-
name = "
|
26
|
+
name = "xml_#{match[1].downcase.gsub(' ', '_')}"
|
27
27
|
value = match[3]
|
28
28
|
attributes[name] = value
|
29
29
|
end while (line = file.readline.strip) != '</dict>'
|
30
|
-
yield(Track.new(attributes)) if attributes['
|
30
|
+
yield(Track.new(attributes)) if attributes['xml_track_type'] == 'File' && attributes['xml_podcast'].blank? && EXTENSIONS.include?(File.extname(attributes['xml_location'].try(:downcase)))
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kagu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.2
|
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: 2019-10-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -130,7 +130,7 @@ dependencies:
|
|
130
130
|
- - "<"
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: 3.8.0
|
133
|
-
description: API to manage
|
133
|
+
description: API to manage macOS Music tracks and playlists
|
134
134
|
email: al@alweb.org
|
135
135
|
executables: []
|
136
136
|
extensions: []
|
@@ -168,9 +168,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
168
|
- !ruby/object:Gem::Version
|
169
169
|
version: '0'
|
170
170
|
requirements: []
|
171
|
-
|
172
|
-
rubygems_version: 2.7.6
|
171
|
+
rubygems_version: 3.0.3
|
173
172
|
signing_key:
|
174
173
|
specification_version: 4
|
175
|
-
summary: API for
|
174
|
+
summary: API for macOS Music
|
176
175
|
test_files: []
|