nehm 1.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.
@@ -0,0 +1,13 @@
1
+ require 'soundcloud'
2
+ require_relative 'config.rb'
3
+
4
+ module Client
5
+ # SSL Certificate
6
+ ENV['SSL_CERT_FILE'] = File.join(__dir__, 'cacert.pem')
7
+
8
+ CLIENT_ID = '11a37feb6ccc034d5975f3f803928a32'
9
+
10
+ def self.new
11
+ @client ||= Soundcloud.new(client_id: CLIENT_ID)
12
+ end
13
+ end
@@ -0,0 +1,46 @@
1
+ require 'yaml'
2
+
3
+ module Config
4
+ # Public
5
+
6
+ def self.[](key)
7
+ config_hash = load_config
8
+ config_hash[key.to_s]
9
+ end
10
+
11
+ def self.[]=(key, value)
12
+ config_hash = load_config
13
+ config_hash[key.to_s] = value
14
+ save_config(config_hash)
15
+ end
16
+
17
+ def self.create
18
+ File.open(file_path, 'w+') { |f| f.write("---\napp: nehm")}
19
+ end
20
+
21
+ def self.exist?
22
+ File.exist?(file_path)
23
+ end
24
+
25
+ def self.key?(key)
26
+ load_config.key?(key.to_s)
27
+ end
28
+
29
+ # Private
30
+
31
+ module_function
32
+
33
+ def file_path
34
+ File.join(ENV['HOME'], '.nehmconfig')
35
+ end
36
+
37
+ def load_config
38
+ file = file_path
39
+ YAML.load_file(file)
40
+ end
41
+
42
+ def save_config(config_hash)
43
+ file = file_path
44
+ IO.write(file, config_hash.to_yaml)
45
+ end
46
+ end
@@ -0,0 +1,24 @@
1
+ require 'highline'
2
+ require 'paint'
3
+ require_relative 'user_control.rb'
4
+ require_relative 'os.rb'
5
+ require_relative 'config.rb'
6
+ require_relative 'path_control.rb'
7
+
8
+ module Configure
9
+ def self.menu
10
+ puts 'Download path: ' + Paint[PathControl.dl_path, :magenta]
11
+ puts 'iTunes path: ' + Paint[PathControl.itunes_path.sub("/iTunes\ Media/Automatically\ Add\ to\ iTunes.localized", ''), :magenta] unless OS.linux?
12
+ puts 'Permalink: ' + Paint[Config[:permalink], :cyan]
13
+ puts "\n"
14
+
15
+ HighLine.new.choose do |menu|
16
+ menu.prompt = Paint['Choose setting', :yellow]
17
+
18
+ menu.choice('Edit download path') { PathControl.set_dl_path }
19
+ menu.choice('Edit itunes path') { PathControl.set_itunes_path } unless OS.linux?
20
+ menu.choice('Edit permalink') { UserControl.log_in }
21
+ menu.choice('Exit') { exit }
22
+ end
23
+ end
24
+ end
data/lib/nehm/help.rb ADDED
@@ -0,0 +1,57 @@
1
+ module Help
2
+
3
+ # Public
4
+
5
+ def self.available_commands
6
+ puts Paint['Avalaible nehm commands:', :yellow]
7
+ puts ' ' + Paint['get', :green] + ' - Downloading, setting tags and adding to your iTunes library last post or like from your profile'
8
+ puts ' ' + Paint['dl', :green] + ' - Downloading and setting tags last post or like from your profile'
9
+ puts ' ' + Paint['configure', :green] + ' - Configuring application'
10
+ puts "See #{Paint['nehm help [command]']} to read about a specific subcommand"
11
+ end
12
+
13
+ def self.show(command)
14
+ case command
15
+ when 'get', 'dl', 'configure'
16
+ Help.send(command)
17
+ else
18
+ Help.available_commands
19
+ end
20
+ end
21
+
22
+ # Private
23
+
24
+ module_function
25
+
26
+ def permalink
27
+ puts 'Permalink is the last word in your profile url'
28
+ puts 'Example: for profile url ' + Paint['soundcloud.com/qwerty', :magenta] + ' permalink is ' + Paint['qwerty', :magenta]
29
+ end
30
+
31
+ def get
32
+ puts Paint['Input: ', :yellow] + 'nehm get [options]'
33
+
34
+ puts Paint['Available options:', :yellow]
35
+ puts ' ' + Paint['track', :green] + ' - Downloading, setting tags and adding to your iTunes library last post(track or repost) from your profile'
36
+ puts ' ' + Paint['[number] tracks', :green] + ' - Downloading, setting tags and adding to your iTunes library last [number] posts from your profile'
37
+ puts ' ' + Paint['like', :green] + ' - Downloading, setting tags and adding to your iTunes library your last like'
38
+ puts ' ' + Paint['[number] likes', :green] + ' - Downloading, setting tags and adding to your iTunes library your last [number] likes'
39
+ end
40
+
41
+ def dl
42
+ puts Paint['Input: ', :yellow] + 'nehm dl [options]'
43
+
44
+ puts Paint['Available options:', :yellow]
45
+ puts ' ' + Paint['track', :green] + ' - Downloading and setting tags last post(track or repost) from your profile'
46
+ puts ' ' + Paint['[number] tracks', :green] + ' - Downloading and setting tags last [number] posts from your profile'
47
+ puts ' ' + Paint['like', :green] + ' - Downloading and setting tags your last like'
48
+ puts ' ' + Paint['[number] likes', :green] + ' - Downloading and setting tags your last [number] likes'
49
+ end
50
+
51
+ def configure
52
+ puts Paint['Input: ', :yellow] + 'nehm configure'
53
+
54
+ puts Paint['Available options:', :yellow]
55
+ puts ' No options'
56
+ end
57
+ end
data/lib/nehm/os.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'rbconfig'
2
+ module OS
3
+ def self.linux?
4
+ host_os = RbConfig::CONFIG['host_os']
5
+ host_os =~ /linux/ ? true : false
6
+ end
7
+ end
@@ -0,0 +1,48 @@
1
+ require 'highline'
2
+ require_relative 'config.rb'
3
+ module PathControl
4
+ def self.dl_path
5
+ Config[:dl_path]
6
+ end
7
+
8
+ def self.set_dl_path
9
+ loop do
10
+ default_path = File.join(ENV['HOME'], '/Music')
11
+ path = HighLine.new.ask("Enter a FULL path to desirable download directory (press enter to set it to #{default_path}): ")
12
+ path = default_path if path == ''
13
+
14
+ if Dir.exist?(path)
15
+ Config[:dl_path] = path
16
+ puts Paint['Download directory set up!', :green]
17
+ break
18
+ else
19
+ puts "\n"
20
+ puts Paint["This directory doesn't exist. Please enter path again", :red]
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.itunes_path
26
+ Config[:itunes_path]
27
+ end
28
+
29
+ def self.set_itunes_path
30
+ loop do
31
+ default_path = File.join(ENV['HOME'], '/Music/iTunes')
32
+ path = HighLine.new.ask("Enter a FULL path to iTunes directory (press enter to set it to #{default_path}): ")
33
+ path = default_path if path == ''
34
+
35
+ path = File.join(path, "iTunes\ Media/Automatically\ Add\ to\ iTunes.localized")
36
+
37
+ if Dir.exist?(path)
38
+ Config[:itunes_path] = path
39
+ puts Paint['iTunes directory set up!', :green]
40
+ break
41
+ else
42
+ puts "\n"
43
+ puts Paint["This directory doesn't exist. Please enter path again", :red]
44
+ end
45
+
46
+ end
47
+ end
48
+ end
data/lib/nehm/track.rb ADDED
@@ -0,0 +1,49 @@
1
+ require_relative 'client.rb'
2
+ require_relative 'artwork.rb'
3
+ require_relative 'path_control.rb'
4
+
5
+ class Track
6
+ attr_reader :hash
7
+
8
+ def initialize(hash)
9
+ @hash = hash
10
+ end
11
+
12
+ def artist
13
+ if @hash['title'].include?('-')
14
+ title = @hash['title'].split('-')
15
+ title[0].rstrip
16
+ else
17
+ @hash['user']['username']
18
+ end
19
+ end
20
+
21
+ def title
22
+ if @hash['title'].include?('-')
23
+ title = @hash['title'].split('-')
24
+ title[1].lstrip
25
+ else
26
+ @hash['title']
27
+ end
28
+ end
29
+
30
+ def artwork
31
+ Artwork.new(self)
32
+ end
33
+
34
+ def dl_url
35
+ "#{@hash['stream_url']}?client_id=#{Client::CLIENT_ID}"
36
+ end
37
+
38
+ def file_name
39
+ "#{artist} - #{title}.mp3".tr('/', '')
40
+ end
41
+
42
+ def file_path
43
+ File.join(PathControl.dl_path, file_name)
44
+ end
45
+
46
+ def id
47
+ @hash['id'].to_s
48
+ end
49
+ end
@@ -0,0 +1,96 @@
1
+ require 'taglib'
2
+ require 'fileutils'
3
+ require 'paint'
4
+ require_relative 'path_control.rb'
5
+ require_relative 'client.rb'
6
+ require_relative 'user.rb'
7
+ require_relative 'track.rb'
8
+ require_relative 'os.rb'
9
+
10
+ module TrackUtils
11
+ # Public
12
+
13
+ def self.get(dl, args)
14
+ tracks = []
15
+ tracks +=
16
+ case args.last
17
+ when 'like'
18
+ User.new.likes(1)
19
+ when 'post'
20
+ User.new.posts(1)
21
+ when 'likes'
22
+ count = args[-2].to_i
23
+ User.new.likes(count)
24
+ when 'posts'
25
+ count = args[-2].to_i
26
+ User.new.posts(count)
27
+ when %r{https:\/\/soundcloud.com\/}
28
+ track_from_url(args.last)
29
+ else
30
+ puts Paint['Invalid argument(s)', :red]
31
+ puts "Input #{Paint['nehm help', :yellow]} for help"
32
+ exit
33
+ end
34
+
35
+ tracks.each do |track|
36
+ dl(track)
37
+ tag(track)
38
+ cp(track) unless (dl == :dl) || (OS.linux?)
39
+ track.artwork.suicide
40
+ end
41
+ puts Paint['Done!', :green]
42
+ end
43
+
44
+ # Private
45
+
46
+ module_function
47
+
48
+ def track_from_url(url)
49
+ client = Client.new
50
+ track = client.get('/resolve', url: url)
51
+ tracks = []
52
+ tracks << Track.new(track)
53
+ end
54
+
55
+ def dl(track)
56
+ # Downloading track and artwork
57
+ puts 'Downloading ' + track.artist + ' - ' + track.title
58
+ path = track.file_path
59
+ dl_url = track.dl_url
60
+ command = "curl -# -o '" + path + "' -L " + dl_url
61
+ system(command)
62
+
63
+ puts 'Downloading artwork'
64
+ artwork = track.artwork
65
+ path = artwork.file_path
66
+ dl_url = artwork.dl_url
67
+ command = "curl -# -o '" + path + "' -L " + dl_url
68
+ system(command)
69
+ end
70
+
71
+ def tag(track)
72
+ path = track.file_path
73
+ TagLib::MPEG::File.open(path) do |file|
74
+ puts 'Setting tags'
75
+ #TODO: Add more tags (year)
76
+ tag = file.id3v2_tag
77
+ tag.artist = track.artist
78
+ tag.title = track.title
79
+
80
+ # Adding artwork
81
+ apic = TagLib::ID3v2::AttachedPictureFrame.new
82
+ apic.mime_type = 'image/jpeg'
83
+ apic.description = 'Cover'
84
+ apic.type = TagLib::ID3v2::AttachedPictureFrame::FrontCover
85
+ apic.picture = File.open(track.artwork.file_path, 'rb') { |f| f.read }
86
+ tag.add_frame(apic)
87
+
88
+ file.save
89
+ end
90
+ end
91
+
92
+ def cp(track)
93
+ puts 'Adding to iTunes library'
94
+ FileUtils.cp(track.file_path, PathControl.itunes_path)
95
+ end
96
+ end
data/lib/nehm/user.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'json'
2
+ require 'faraday'
3
+ require_relative 'client.rb'
4
+ require_relative 'config.rb'
5
+ require_relative 'user_control.rb'
6
+
7
+ class User
8
+ def initialize(permalink = nil)
9
+ client = Client.new
10
+ @id =
11
+ unless permalink.nil?
12
+ user = client.get('/resolve', url: "https://soundcloud.com/#{permalink}")
13
+ user.id
14
+ else
15
+ UserControl.default_id
16
+ end
17
+ end
18
+
19
+ def likes(count)
20
+ client = Client.new
21
+ likes = client.get("/users/#{@id}/favorites?limit=#{count}")
22
+ likes.map { |like| Track.new(like) }
23
+ end
24
+
25
+ def posts(count)
26
+ conn = Faraday.new(url: 'https://api-v2.soundcloud.com/') do |faraday|
27
+ faraday.request :url_encoded # form-encode POST params
28
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
29
+ end
30
+
31
+ response = conn.get("/profile/soundcloud:users:#{@id}?limit=#{count}&offset=0")
32
+
33
+ parsed = JSON.parse(response.body)
34
+ parsed = parsed['collection']
35
+ parsed.map { |track| Track.new(track['track']) }
36
+ end
37
+ end
@@ -0,0 +1,49 @@
1
+ require 'highline'
2
+ require 'paint'
3
+ require_relative 'config.rb'
4
+ require_relative 'client.rb'
5
+
6
+ module UserControl
7
+ def self.logged_in?
8
+ Config.key?(:default_id)
9
+ end
10
+
11
+ def self.log_in
12
+ loop do
13
+ permalink = HighLine.new.ask('Please enter your permalink (last word in your profile url): ')
14
+ client = Client.new
15
+ url = "https://soundcloud.com/#{permalink}"
16
+ if UserControl.exist?(url)
17
+ user = client.get('/resolve', url: url)
18
+ Config[:default_id] = user.id
19
+ Config[:permalink] = permalink
20
+ puts Paint['Successfully logged in!', :green]
21
+ break
22
+ else
23
+ puts Paint['Invalid permalink. Please enter correct permalink', :red]
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.default_id
29
+ if UserControl.logged_in?
30
+ Config[:default_id]
31
+ else
32
+ puts "You didn't logged in"
33
+ puts "Input #{Paint['nehm configure', :yellow]} to login"
34
+ exit
35
+ end
36
+ end
37
+
38
+ def self.exist?(url)
39
+ Client.new.get('/resolve', url: url)
40
+ rescue SoundCloud::ResponseError => e
41
+ if e.message =~ /404/
42
+ raise e
43
+ else
44
+ false
45
+ end
46
+ else
47
+ true
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module Nehm
2
+ VERSION = '1.0.2'
3
+ end
data/lib/nehm.rb ADDED
@@ -0,0 +1,53 @@
1
+ require_relative 'nehm/os.rb'
2
+ require_relative 'nehm/track_utils.rb'
3
+ require_relative 'nehm/path_control.rb'
4
+ require_relative 'nehm/user_control.rb'
5
+ require_relative 'nehm/config.rb'
6
+ require_relative 'nehm/configure.rb'
7
+ require_relative 'nehm/help.rb'
8
+ module App
9
+ # Public
10
+
11
+ def self.do(args)
12
+ init unless initialized?
13
+
14
+ command = args.shift
15
+ case command
16
+ when 'get'
17
+ TrackUtils.get(:get, args)
18
+ when 'dl'
19
+ TrackUtils.get(:dl, args)
20
+ when 'configure'
21
+ Configure.menu
22
+ when 'login'
23
+ UserControl.log_in
24
+ when 'init'
25
+ init
26
+ when 'help'
27
+ Help.show(args.first)
28
+ else
29
+ puts Paint['Invalid command', :red]
30
+ puts "Input #{Paint['nehm help', :yellow]} for all avalaible commands"
31
+ end
32
+ end
33
+
34
+ # Private
35
+
36
+ module_function
37
+
38
+ def init
39
+ puts Paint['Hello!', :green]
40
+ puts 'Before using the nehm, you should set it up:'
41
+ Config.create unless Config.exist?
42
+ PathControl.set_dl_path
43
+ puts "\n"
44
+ PathControl.set_itunes_path unless OS.linux?
45
+ puts "\n" unless OS.linux?
46
+ UserControl.log_in
47
+ puts Paint['Now you can use nehm :)', :green]
48
+ end
49
+
50
+ def initialized?
51
+ File.exist?(File.join(ENV['HOME'], '.nehmconfig'))
52
+ end
53
+ end
data/nehm.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nehm/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'nehm'
8
+ spec.version = Nehm::VERSION
9
+ spec.authors = ['Albert Nigmatzianov']
10
+ spec.email = ['albertnigma@gmail.com']
11
+
12
+ spec.summary = %q{Convenient way to get tracks from SoundCloud}
13
+ spec.description = %q{nehm is a console tool, which downloads, sets IDv3 tags and adds to your iTunes library your SoundCloud posts or likes (also by url) in convenient way}
14
+ spec.homepage = 'http://www.github.com/bogem/nehm'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'bin'
19
+ spec.executables = 'nehm'
20
+ spec.require_paths = ['lib']
21
+ spec.required_ruby_version = '>= 1.9'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 3.2', '>= 3.2.2'
24
+ spec.add_development_dependency 'rake', '~> 10.4', '>= 10.4.2'
25
+ spec.add_dependency 'soundcloud', '~> 0.3', '>= 0.3.2'
26
+ spec.add_dependency 'taglib-ruby', '~> 0.7', '>= 0.7.0'
27
+ spec.add_dependency 'faraday', '~> 0.9', '>= 0.9.1'
28
+ spec.add_dependency 'highline', '~> 1.7', '>= 1.7.2'
29
+ end