audio_addict 0.4.1 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/radio +8 -12
- data/lib/audio_addict/api.rb +12 -11
- data/lib/audio_addict/cache.rb +2 -2
- data/lib/audio_addict/channel.rb +12 -9
- data/lib/audio_addict/cli.rb +12 -12
- data/lib/audio_addict/commands/api.rb +14 -13
- data/lib/audio_addict/commands/base.rb +3 -3
- data/lib/audio_addict/commands/channels.rb +23 -23
- data/lib/audio_addict/commands/config.rb +57 -57
- data/lib/audio_addict/commands/download.rb +20 -19
- data/lib/audio_addict/commands/history.rb +6 -6
- data/lib/audio_addict/commands/log.rb +37 -35
- data/lib/audio_addict/commands/login.rb +11 -11
- data/lib/audio_addict/commands/now.rb +5 -5
- data/lib/audio_addict/commands/playlist.rb +25 -24
- data/lib/audio_addict/commands/set.rb +24 -22
- data/lib/audio_addict/commands/vote.rb +32 -32
- data/lib/audio_addict/config.rb +7 -3
- data/lib/audio_addict/exceptions.rb +2 -2
- data/lib/audio_addict/extensions/file.rb +18 -14
- data/lib/audio_addict/inspectable.rb +2 -2
- data/lib/audio_addict/log.rb +2 -2
- data/lib/audio_addict/radio.rb +19 -19
- data/lib/audio_addict/track.rb +5 -4
- data/lib/audio_addict/version.rb +1 -1
- data/lib/audio_addict/youtube.rb +6 -4
- data/lib/audio_addict.rb +8 -8
- metadata +8 -7
@@ -1,71 +1,73 @@
|
|
1
1
|
module AudioAddict
|
2
2
|
module Commands
|
3
3
|
class LogCmd < Base
|
4
|
-
summary
|
4
|
+
summary 'Manage local like-log'
|
5
5
|
|
6
|
-
help
|
6
|
+
help 'This command provides access and utilities for the local log of liked tracks. Before you can use this command, make sure you have configured the path to your log.'
|
7
7
|
|
8
|
-
usage
|
9
|
-
usage
|
10
|
-
usage
|
11
|
-
usage
|
12
|
-
usage
|
13
|
-
usage
|
8
|
+
usage 'radio log show [SEARCH]'
|
9
|
+
usage 'radio log tail [--lines N]'
|
10
|
+
usage 'radio log sort'
|
11
|
+
usage 'radio log browse'
|
12
|
+
usage 'radio log tree [--save FILE]'
|
13
|
+
usage 'radio log --help'
|
14
14
|
|
15
|
-
option
|
16
|
-
option
|
15
|
+
option '-l --lines N', 'Number of lines to show [default: 5]'
|
16
|
+
option '-s --save FILE', 'Save the tree output to a YAML file'
|
17
17
|
|
18
|
-
param
|
18
|
+
param 'SEARCH', 'Show only log lines matching this string'
|
19
19
|
|
20
|
-
command
|
21
|
-
command
|
22
|
-
command
|
23
|
-
command
|
24
|
-
command
|
20
|
+
command 'show', 'Show the entire like log'
|
21
|
+
command 'tail', 'Show the last few rows of the like log'
|
22
|
+
command 'sort', 'Sort the log alphabetically and save it'
|
23
|
+
command 'browse', 'Browse the log file interactively'
|
24
|
+
command 'tree', 'Show or save the log as YAML'
|
25
25
|
|
26
|
-
example
|
27
|
-
example
|
28
|
-
example
|
29
|
-
example
|
30
|
-
example
|
31
|
-
example
|
26
|
+
example 'radio log show'
|
27
|
+
example 'radio log show paramore'
|
28
|
+
example 'radio log tail'
|
29
|
+
example 'radio log tail --lines 10'
|
30
|
+
example 'radio log sort'
|
31
|
+
example 'radio log tree --save out.yml'
|
32
32
|
|
33
33
|
def show_command
|
34
34
|
needs :like_log
|
35
|
-
query = args[
|
35
|
+
query = args['SEARCH']
|
36
36
|
puts query ? log.search(query) : log.data
|
37
37
|
end
|
38
38
|
|
39
39
|
def tail_command
|
40
40
|
needs :like_log
|
41
|
-
lines = args[
|
42
|
-
puts log.data[-lines
|
41
|
+
lines = args['--lines'].to_i
|
42
|
+
puts log.data[-lines..]
|
43
43
|
end
|
44
44
|
|
45
45
|
def sort_command
|
46
46
|
needs :like_log
|
47
47
|
log.sort
|
48
|
-
say
|
48
|
+
say '!txtgrn!Sorted'
|
49
49
|
end
|
50
50
|
|
51
51
|
def browse_command
|
52
52
|
tree = log.tree
|
53
53
|
|
54
|
-
say
|
55
|
-
network = prompt.select
|
56
|
-
channel = prompt.select
|
57
|
-
|
54
|
+
say ''
|
55
|
+
network = prompt.select 'Network:', tree.keys, symbols: { marker: '>' }, filter: true, per_page: 10
|
56
|
+
channel = prompt.select 'Channel:', tree[network].keys, symbols: { marker: '>' }, filter: true,
|
57
|
+
per_page: page_size
|
58
|
+
artist = prompt.select 'Artist:', tree[network][channel].keys, symbols: { marker: '>' }, filter: true,
|
59
|
+
per_page: page_size
|
58
60
|
|
59
|
-
say
|
61
|
+
say 'Songs:'
|
60
62
|
tree[network][channel][artist].each { |song| say "- !txtgrn!#{song}" }
|
61
|
-
say
|
63
|
+
say ''
|
62
64
|
|
63
|
-
browse_command if prompt.yes?(
|
65
|
+
browse_command if prompt.yes?('Again?')
|
64
66
|
end
|
65
67
|
|
66
68
|
def tree_command
|
67
69
|
yaml = log.tree.to_yaml
|
68
|
-
filename = args[
|
70
|
+
filename = args['--save']
|
69
71
|
|
70
72
|
if filename
|
71
73
|
File.write filename, yaml
|
@@ -75,7 +77,7 @@ module AudioAddict
|
|
75
77
|
end
|
76
78
|
end
|
77
79
|
|
78
|
-
|
80
|
+
private
|
79
81
|
|
80
82
|
def log
|
81
83
|
@log ||= Log.new
|
@@ -1,36 +1,36 @@
|
|
1
1
|
module AudioAddict
|
2
2
|
module Commands
|
3
3
|
class LoginCmd < Base
|
4
|
-
summary
|
4
|
+
summary 'Save login credentials'
|
5
5
|
|
6
6
|
help "Some commands in this AudioAddict CLI require access to the AudioAddict API. The 'login' command requests your AudioAddict user and password, and stores an API session key. This operation needs to be executed only once.\n\nThe user and password are not stored anywhere, only the session key is stored in your local configuration file."
|
7
7
|
|
8
|
-
usage
|
9
|
-
usage
|
8
|
+
usage 'radio login'
|
9
|
+
usage 'radio login --help'
|
10
10
|
|
11
11
|
def run
|
12
12
|
proceed = true
|
13
13
|
|
14
14
|
if radio.api.logged_in?
|
15
15
|
say "!txtylw!You are already logged in as !undylw!#{Config.email}"
|
16
|
-
proceed = prompt.yes?
|
16
|
+
proceed = prompt.yes? 'Login again?'
|
17
17
|
end
|
18
18
|
|
19
19
|
login_prompt if proceed
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
private
|
23
23
|
|
24
24
|
def login_prompt
|
25
|
-
user = prompt.ask
|
26
|
-
pass = prompt.mask
|
25
|
+
user = prompt.ask 'Username :', default: Config.email
|
26
|
+
pass = prompt.mask 'Password :'
|
27
27
|
|
28
|
-
if user
|
29
|
-
say
|
28
|
+
if user && pass
|
29
|
+
say 'Logging in... '
|
30
30
|
radio.api.login user, pass
|
31
|
-
resay
|
31
|
+
resay '!txtgrn!Saved'
|
32
32
|
else
|
33
|
-
say
|
33
|
+
say '!txtred!Cancelled'
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
module AudioAddict
|
2
2
|
module Commands
|
3
3
|
class NowCmd < Base
|
4
|
-
summary
|
4
|
+
summary 'Show network, channel and playing track'
|
5
5
|
|
6
|
-
help
|
6
|
+
help 'This command displays the active network and channel, as well as the currently playing track.'
|
7
7
|
|
8
|
-
usage
|
9
|
-
usage
|
8
|
+
usage 'radio now'
|
9
|
+
usage 'radio now --help'
|
10
10
|
|
11
11
|
def run
|
12
12
|
needs :network, :channel
|
13
13
|
|
14
14
|
say "!txtblu! Network !txtrst!: !txtgrn!#{radio.name}!txtrst! # #{radio.network}"
|
15
15
|
say "!txtblu! Channel !txtrst!: !txtgrn!#{current_channel.name}!txtrst! # #{current_channel.key}"
|
16
|
-
say
|
16
|
+
say '!txtblu! Track !txtrst!: ... '
|
17
17
|
|
18
18
|
track = current_channel.current_track
|
19
19
|
resay "!txtblu! Track !txtrst!: !txtgrn!#{track.title.strip}"
|
@@ -1,37 +1,38 @@
|
|
1
1
|
module AudioAddict
|
2
2
|
module Commands
|
3
3
|
class PlaylistCmd < Base
|
4
|
-
summary
|
4
|
+
summary 'Generate playlists'
|
5
5
|
|
6
6
|
help "This command lets you generate playlists for the active network. In order to allow configuration, the process is done in two stages: 'init' and 'generate'."
|
7
7
|
|
8
|
-
usage
|
9
|
-
usage
|
10
|
-
usage
|
8
|
+
usage 'radio playlist init NAME'
|
9
|
+
usage 'radio playlist generate NAME'
|
10
|
+
usage 'radio playlist --help'
|
11
11
|
|
12
|
-
command
|
13
|
-
|
12
|
+
command 'init',
|
13
|
+
'Create a playlist configuration file. This step is required prior to using the generate command. After you generate this file, feel free to edit it to your preferences (sort order, remove channels etc).'
|
14
|
+
command 'generate', 'Generate a playlist file based on the configuration file.'
|
14
15
|
|
15
|
-
param
|
16
|
+
param 'NAME', 'The name of the playlist without any extension'
|
16
17
|
|
17
|
-
example
|
18
|
-
example
|
18
|
+
example 'radio playlist init MyRockMusic'
|
19
|
+
example 'radio playlist generate MyRockMusic'
|
19
20
|
|
20
21
|
def init_command
|
21
22
|
needs :network, :channel, :listen_key
|
22
23
|
|
23
24
|
require_premium_account
|
24
25
|
|
25
|
-
name = args[
|
26
|
+
name = args['NAME']
|
26
27
|
outfile = "#{name}.yml"
|
27
28
|
|
28
29
|
say "!txtred!Warning!txtrst!: !txtgrn!#{outfile}!txtrst! already exists!" if File.exist? outfile
|
29
30
|
proceed = prompt.yes? "Create #{outfile}?"
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
return unless proceed
|
32
|
+
|
33
|
+
generate_config outfile
|
34
|
+
say ''
|
35
|
+
generate_command name
|
35
36
|
end
|
36
37
|
|
37
38
|
def generate_command(name = nil)
|
@@ -39,21 +40,21 @@ module AudioAddict
|
|
39
40
|
|
40
41
|
require_premium_account
|
41
42
|
|
42
|
-
name ||= args[
|
43
|
+
name ||= args['NAME']
|
43
44
|
|
44
45
|
infile = "#{name}.yml"
|
45
46
|
outfile = "#{name}.pls"
|
46
47
|
|
47
|
-
if
|
48
|
-
say "!txtred!Cannot find #{infile}"
|
49
|
-
else
|
48
|
+
if File.exist? infile
|
50
49
|
say "!txtred!Warning!txtrst!: !txtgrn!#{outfile}!txtrst! already exists!" if File.exist? outfile
|
51
50
|
proceed = prompt.yes? "Create #{outfile}?"
|
52
51
|
generate_playlist infile, outfile if proceed
|
52
|
+
else
|
53
|
+
say "!txtred!Cannot find #{infile}"
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
|
-
|
57
|
+
private
|
57
58
|
|
58
59
|
def generate_config(outfile)
|
59
60
|
data = { template: radio.url_template }
|
@@ -76,19 +77,19 @@ module AudioAddict
|
|
76
77
|
channels = data[:channels]
|
77
78
|
|
78
79
|
output = []
|
79
|
-
output <<
|
80
|
+
output << '[playlist]'
|
80
81
|
output << "NumberOfEntries=#{channels.count}"
|
81
82
|
|
82
83
|
index = 0
|
83
84
|
|
84
85
|
channels.each do |key, name|
|
85
86
|
index += 1
|
86
|
-
output << "File#{index}=#{template}" % template_params(key)
|
87
|
+
output << ("File#{index}=#{template}" % template_params(key))
|
87
88
|
output << "Title#{index}=#{name}"
|
88
89
|
output << "Length#{index}=0"
|
89
90
|
end
|
90
91
|
|
91
|
-
output = output.join("\n")
|
92
|
+
output = "#{output.join("\n")}\n"
|
92
93
|
|
93
94
|
File.write outfile, output
|
94
95
|
say "Saved !txtgrn!#{outfile}"
|
@@ -104,7 +105,7 @@ module AudioAddict
|
|
104
105
|
|
105
106
|
# This is a patch to circumvent some anomalies in the AudioAddict API
|
106
107
|
def fix_key(key)
|
107
|
-
key = :electrohouse if current_network ==
|
108
|
+
key = :electrohouse if (current_network == 'di') && (key == :electro)
|
108
109
|
key
|
109
110
|
end
|
110
111
|
end
|
@@ -1,26 +1,28 @@
|
|
1
1
|
module AudioAddict
|
2
2
|
module Commands
|
3
3
|
class SetCmd < Base
|
4
|
-
summary
|
4
|
+
summary 'Set the radio network and channel'
|
5
5
|
|
6
|
-
help
|
6
|
+
help 'This command provides both interactive and non-interactive means of storing the currenlty active channel and network in the configuration file.'
|
7
7
|
|
8
|
-
usage
|
9
|
-
usage
|
8
|
+
usage 'radio set [CHANNEL NETWORK]'
|
9
|
+
usage 'radio set --help'
|
10
10
|
|
11
|
-
param
|
12
|
-
|
11
|
+
param 'CHANNEL',
|
12
|
+
"AudioAddict channel key. You can use a partial key here or leave empty for an interactive prompt.\nUse '-' to set the first channel in the network."
|
13
|
+
param 'NETWORK',
|
14
|
+
'AudioAddict network key. You can use a partial key here or leave empty for an interactive prompt.'
|
13
15
|
|
14
|
-
example
|
15
|
-
example
|
16
|
-
example
|
17
|
-
example
|
18
|
-
example
|
19
|
-
example
|
16
|
+
example 'radio set'
|
17
|
+
example 'radio set punk'
|
18
|
+
example 'radio set dance digitally'
|
19
|
+
example 'radio set dance di'
|
20
|
+
example 'radio set metal rockradio'
|
21
|
+
example 'radio set - rockradio'
|
20
22
|
|
21
23
|
def run
|
22
|
-
channel = args[
|
23
|
-
network = args[
|
24
|
+
channel = args['CHANNEL']
|
25
|
+
network = args['NETWORK']
|
24
26
|
|
25
27
|
full_set = (channel and network) || !(channel or network)
|
26
28
|
|
@@ -31,12 +33,12 @@ module AudioAddict
|
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
|
36
|
+
private
|
35
37
|
|
36
38
|
def set_both(channel, network)
|
37
39
|
needs :session_key
|
38
40
|
|
39
|
-
if !network
|
41
|
+
if !network || !Radio.valid_network?(network)
|
40
42
|
network_menu network
|
41
43
|
elsif Radio.valid_network? network
|
42
44
|
save_network network
|
@@ -50,7 +52,7 @@ module AudioAddict
|
|
50
52
|
|
51
53
|
if !channel
|
52
54
|
channel_menu
|
53
|
-
elsif channel ==
|
55
|
+
elsif channel == '-'
|
54
56
|
save_channel radio.channels.keys.first
|
55
57
|
elsif radio.valid_channel? channel
|
56
58
|
save_channel channel
|
@@ -84,15 +86,15 @@ module AudioAddict
|
|
84
86
|
end
|
85
87
|
|
86
88
|
def channel_prompt(channels)
|
87
|
-
options = channels.
|
88
|
-
options = {
|
89
|
-
prompt.select
|
89
|
+
options = channels.to_h { |channel| ["#{channel.name.ljust 20} # #{channel.key}", channel.key] }
|
90
|
+
options = { 'Cancel' => :cancel }.merge options
|
91
|
+
prompt.select 'Channel :', options, symbols: { marker: '>' }, filter: true
|
90
92
|
end
|
91
93
|
|
92
94
|
def network_prompt(networks)
|
93
95
|
options = networks.invert
|
94
|
-
options[
|
95
|
-
prompt.select
|
96
|
+
options['Skip'] = :cancel
|
97
|
+
prompt.select 'Network :', options, symbols: { marker: '>' }, filter: true, per_page: 10
|
96
98
|
end
|
97
99
|
|
98
100
|
def save_channel(channel, echo: true)
|
@@ -1,48 +1,48 @@
|
|
1
1
|
module AudioAddict
|
2
2
|
module Commands
|
3
3
|
class VoteCmd < Base
|
4
|
-
summary
|
4
|
+
summary 'Vote on a recently played track'
|
5
5
|
|
6
|
-
help
|
6
|
+
help 'This command starts an interactive voting prompt for the currently playing track or for previously played tracks.'
|
7
7
|
|
8
|
-
usage
|
9
|
-
usage
|
8
|
+
usage 'radio vote [--all --past]'
|
9
|
+
usage 'radio vote --help'
|
10
10
|
|
11
|
-
option
|
12
|
-
option
|
11
|
+
option '-a --all', 'Show all voting options'
|
12
|
+
option '-p --past', 'Vote on previously played tracks'
|
13
13
|
|
14
|
-
example
|
15
|
-
example
|
16
|
-
example
|
17
|
-
example
|
18
|
-
example
|
14
|
+
example 'radio vote'
|
15
|
+
example 'radio vote --all'
|
16
|
+
example 'radio vote --past'
|
17
|
+
example 'radio vote --all --past'
|
18
|
+
example 'radio vote -ap'
|
19
19
|
|
20
20
|
def run
|
21
21
|
needs :network, :channel, :session_key
|
22
22
|
vote_mode == :now ? vote_now : vote_past
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
private
|
26
26
|
|
27
27
|
def vote_past
|
28
|
-
track =
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
track = user_track
|
29
|
+
return if track == :cancel
|
30
|
+
|
31
|
+
vote = user_vote
|
32
|
+
send_vote vote, track unless vote == :cancel
|
33
33
|
end
|
34
34
|
|
35
35
|
def vote_now
|
36
36
|
NowCmd.new(args).run
|
37
|
-
puts
|
38
|
-
vote =
|
37
|
+
puts ''
|
38
|
+
vote = user_vote
|
39
39
|
send_vote vote unless vote == :cancel
|
40
40
|
end
|
41
41
|
|
42
42
|
def send_vote(vote, track = nil)
|
43
|
-
say
|
43
|
+
say 'Voting... '
|
44
44
|
current_channel.vote vote, track: track
|
45
|
-
resay
|
45
|
+
resay '!txtgrn!Voted'
|
46
46
|
end
|
47
47
|
|
48
48
|
def tracks
|
@@ -53,33 +53,33 @@ module AudioAddict
|
|
53
53
|
tracks.map { |t| t.artist.size }.max
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
57
|
-
options = tracks.
|
58
|
-
options = {
|
59
|
-
prompt.select
|
56
|
+
def user_track
|
57
|
+
options = tracks.to_h { |t| ["#{t.artist.ljust max_artist_len} > #{t.title}", t] }
|
58
|
+
options = { 'Cancel' => :cancel }.merge options
|
59
|
+
prompt.select 'Track:', options, symbols: { marker: '>' }
|
60
60
|
end
|
61
61
|
|
62
|
-
def
|
62
|
+
def user_vote
|
63
63
|
vote_style == :menu ? menu_prompt : simple_prompt
|
64
64
|
end
|
65
65
|
|
66
66
|
def menu_prompt
|
67
|
-
options = {
|
68
|
-
|
69
|
-
prompt.select
|
67
|
+
options = { 'Like' => :up, 'Dislike' => :down,
|
68
|
+
'Unvote' => :delete, 'Cancel' => :cancel }
|
69
|
+
prompt.select 'Vote:', options, symbols: { marker: '>' }
|
70
70
|
end
|
71
71
|
|
72
72
|
def simple_prompt
|
73
|
-
like = prompt.yes?
|
73
|
+
like = prompt.yes? 'Vote?'
|
74
74
|
like ? :up : :cancel
|
75
75
|
end
|
76
76
|
|
77
77
|
def vote_style
|
78
|
-
args[
|
78
|
+
args['--all'] ? :menu : :simple
|
79
79
|
end
|
80
80
|
|
81
81
|
def vote_mode
|
82
|
-
args[
|
82
|
+
args['--past'] ? :past : :now
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
data/lib/audio_addict/config.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'yaml'
|
2
2
|
|
3
3
|
module AudioAddict
|
4
4
|
class Config
|
@@ -6,7 +6,7 @@ module AudioAddict
|
|
6
6
|
attr_writer :path
|
7
7
|
|
8
8
|
def method_missing(name, *args, &_blk)
|
9
|
-
if name.to_s.end_with?
|
9
|
+
if name.to_s.end_with? '='
|
10
10
|
name = name[0..-2].to_sym
|
11
11
|
properties[name] = args.first
|
12
12
|
else
|
@@ -14,6 +14,10 @@ module AudioAddict
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
def respond_to_missing?(*_args)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
17
21
|
def delete(*keys)
|
18
22
|
keys.each { |key| properties.delete key.to_sym }
|
19
23
|
end
|
@@ -39,7 +43,7 @@ module AudioAddict
|
|
39
43
|
end
|
40
44
|
|
41
45
|
def path
|
42
|
-
@path ||= ENV.fetch(
|
46
|
+
@path ||= ENV.fetch('AUDIO_ADDICT_CONFIG_PATH', default_path)
|
43
47
|
end
|
44
48
|
|
45
49
|
def default_path
|
@@ -9,12 +9,12 @@ module AudioAddict
|
|
9
9
|
|
10
10
|
def initialize(missing_keys)
|
11
11
|
@missing_keys = missing_keys
|
12
|
-
super
|
12
|
+
super 'Some parameters required by this operation are missing'
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
class PremiumAccount < Error
|
17
|
-
def initialize(message =
|
17
|
+
def initialize(message = 'This operation requires a premium account')
|
18
18
|
super
|
19
19
|
end
|
20
20
|
end
|
@@ -1,21 +1,25 @@
|
|
1
|
-
require
|
1
|
+
require 'fileutils'
|
2
2
|
|
3
3
|
class File
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
class << self
|
5
|
+
def contains?(file, content)
|
6
|
+
return false unless File.exist? file
|
7
|
+
|
8
|
+
foreach file do |line|
|
9
|
+
return true if line.chomp == content
|
10
|
+
end
|
11
|
+
|
12
|
+
false
|
8
13
|
end
|
9
|
-
return false
|
10
|
-
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
+
def append(file, content)
|
16
|
+
File.open(file, 'a') { |f| f << "#{content}\n" }
|
17
|
+
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
def deep_write(file, content)
|
20
|
+
dir = File.dirname file
|
21
|
+
FileUtils.mkdir_p dir unless Dir.exist? dir
|
22
|
+
File.write file, content
|
23
|
+
end
|
20
24
|
end
|
21
25
|
end
|
data/lib/audio_addict/log.rb
CHANGED
@@ -21,7 +21,7 @@ module AudioAddict
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def sort
|
24
|
-
output = data.sort.join("\n")
|
24
|
+
output = "#{data.sort.join("\n")}\n"
|
25
25
|
File.write path, output
|
26
26
|
end
|
27
27
|
|
@@ -33,7 +33,7 @@ module AudioAddict
|
|
33
33
|
result = {}
|
34
34
|
|
35
35
|
data.each do |line|
|
36
|
-
network, channel, artist, song = line.split(
|
36
|
+
network, channel, artist, song = line.split(' :: ')
|
37
37
|
result[network] ||= {}
|
38
38
|
result[network][channel] ||= {}
|
39
39
|
result[network][channel][artist] ||= []
|