rmd 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rmd/version.rb +1 -1
- metadata +2 -48
- data/.bundle/config +0 -2
- data/.gitignore +0 -5
- data/.rspec +0 -2
- data/.travis.yml +0 -7
- data/Gemfile +0 -7
- data/LICENSE.txt +0 -22
- data/README.md +0 -63
- data/Rakefile +0 -10
- data/fixtures/vcr_cassettes/nhaccuatui_playlist.yml +0 -124306
- data/fixtures/vcr_cassettes/nhaccuatui_song.yml +0 -32531
- data/fixtures/vcr_cassettes/song_download.yml +0 -186
- data/fixtures/vcr_cassettes/utils_correct_url_correct.yml +0 -40
- data/fixtures/vcr_cassettes/utils_correct_url_redirect.yml +0 -41
- data/fixtures/vcr_cassettes/zing_playlist.yml +0 -69275
- data/fixtures/vcr_cassettes/zing_song.yml +0 -33334
- data/rmd.gemspec +0 -32
- data/spec/acceptants/main_spec.rb +0 -54
- data/spec/rmd/downloader_spec.rb +0 -61
- data/spec/rmd/factory_spec.rb +0 -64
- data/spec/rmd/nct/getter/key_from_page_spec.rb +0 -140
- data/spec/rmd/nct/getter/key_from_url_spec.rb +0 -113
- data/spec/rmd/nct/playlist_spec.rb +0 -46
- data/spec/rmd/nct/song_spec.rb +0 -57
- data/spec/rmd/processor_spec.rb +0 -62
- data/spec/rmd/song_playlist_adapter_spec.rb +0 -35
- data/spec/rmd/zing/playlist_spec.rb +0 -44
- data/spec/rmd/zing/song_spec.rb +0 -92
- data/spec/rmd/zing/utils/correct_url_spec.rb +0 -28
- data/spec/spec_helper.rb +0 -124
- data/spec/support/download_share_examples.rb +0 -9
- data/spec/support/playlist_share_examples.rb +0 -58
data/rmd.gemspec
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'rmd/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "rmd"
|
8
|
-
spec.version = Rmd::VERSION
|
9
|
-
spec.authors = ["Hieu Nguyen"]
|
10
|
-
spec.email = ["hieuk09@gmail.com"]
|
11
|
-
spec.summary = %q{RMD: Ruby Music Dowloader}
|
12
|
-
spec.description = %q{RMD: a music downloader written in pure ruby.}
|
13
|
-
spec.homepage = "https://github.com/hieuk09/rmd"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
spec.executables = 'rmd'
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_dependency 'thor', '~> 0.19'
|
22
|
-
spec.add_dependency 'mechanize', '~> 2.7'
|
23
|
-
spec.add_dependency 'ruby-progressbar', '~> 1.7'
|
24
|
-
spec.add_dependency 'colorize', '~> 0.7'
|
25
|
-
|
26
|
-
spec.add_development_dependency "bundler", "~> 1.6"
|
27
|
-
spec.add_development_dependency "rake", "~> 10.1"
|
28
|
-
spec.add_development_dependency "rspec", '~> 3.1'
|
29
|
-
spec.add_development_dependency "webmock", '~> 1.20'
|
30
|
-
spec.add_development_dependency "vcr", '~> 2.9'
|
31
|
-
spec.add_development_dependency "byebug", '~> 3.5'
|
32
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RMD::Main do
|
4
|
-
describe '#download' do
|
5
|
-
let(:options) { {} }
|
6
|
-
let(:run_method) { RMD::Processor.process(link, options) }
|
7
|
-
let(:file_path) { File.expand_path("../../../#{file_name}", __FILE__) }
|
8
|
-
|
9
|
-
context 'when downloads song from nhaccuatui' do
|
10
|
-
let(:link) { 'http://www.nhaccuatui.com/bai-hat/honjitsu-mijukumono-juken-no-kamisama-ost-tv-version-tokio.tFBwsJKDGQX9.html' }
|
11
|
-
let(:file_name) { 'HonjitsuMijukumonoJukenNoKamisamaOSTTVVersion-TOKIO-3164566.mp3' }
|
12
|
-
let(:scenario) { 'nhaccuatui song'}
|
13
|
-
it_behaves_like 'download'
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'when downloads playlist from nhaccuatui' do
|
17
|
-
let(:link) { 'http://www.nhaccuatui.com/playlist/dev-playlist-dang-cap-nhat.jn0g1fg4Z6UO.html' }
|
18
|
-
let(:file_name) { 'BlazeTvSize-KajiuraYuki_35ax5_hq.mp3' }
|
19
|
-
let(:file_path) { File.expand_path("../../../#{file_name}", __FILE__) }
|
20
|
-
let(:scenario) { 'nhaccuatui playlist' }
|
21
|
-
it_behaves_like 'download'
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when downloads song from zing mp3' do
|
25
|
-
let(:link) { 'http://mp3.zing.vn/bai-hat/Bird-TV-Size-Yuya-Matsushita/ZWZCO98B.html' }
|
26
|
-
let(:file_name) { 'Bird TV Size - Yuya Matsushita.mp3' }
|
27
|
-
let(:scenario) { 'zing song' }
|
28
|
-
it_behaves_like 'download'
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'when downloads playlist from zing mp3' do
|
32
|
-
let(:link) { 'http://mp3.zing.vn/playlist/dev-playlist-zid-sincepast/IO0E698Z.html' }
|
33
|
-
let(:file_name) { 'sharp TV Size - Negoto.mp3' }
|
34
|
-
let(:scenario) { 'zing playlist' }
|
35
|
-
it_behaves_like 'download'
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'when downloads song with options' do
|
39
|
-
let(:link) { 'http://mp3.zing.vn/bai-hat/Bird-TV-Size-Yuya-Matsushita/ZWZCO98B.html' }
|
40
|
-
let(:file_name) { 'Bird TV Size - Yuya Matsushita.mp3' }
|
41
|
-
let(:scenario) { 'zing song' }
|
42
|
-
let(:options) { { folder: 'tmp' } }
|
43
|
-
let(:file_path) { File.expand_path("../../../tmp/#{file_name}", __FILE__) }
|
44
|
-
|
45
|
-
it 'downloads and put to correct folder' do
|
46
|
-
VCR.use_cassette(scenario) do
|
47
|
-
capture_io { run_method }
|
48
|
-
expect(File.exists?(file_path)).to eq true
|
49
|
-
end
|
50
|
-
File.delete(file_path)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
data/spec/rmd/downloader_spec.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RMD::Downloader do
|
4
|
-
describe '.download' do
|
5
|
-
let(:link) { 'www.example/xyz/abc.mp3' }
|
6
|
-
let(:downloader) { instance_double('RMD::Downloader') }
|
7
|
-
|
8
|
-
it 'downloads' do
|
9
|
-
expect(described_class).to receive(:new).with(link, {}).and_return(downloader)
|
10
|
-
expect(downloader).to receive(:download)
|
11
|
-
described_class.download(link)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe '#download' do
|
16
|
-
let(:downloader) { described_class.new(link) }
|
17
|
-
let(:run_method) { downloader.download }
|
18
|
-
let(:scenario) { 'song download' }
|
19
|
-
let(:link) { 'http://db.gamefaqs.com/portable/3ds/file/fire_emblem_awakening_shop.txt' }
|
20
|
-
let(:file_name) { 'fire_emblem_awakening_shop.txt' }
|
21
|
-
let(:file_path) { File.expand_path("../../../#{file_name}", __FILE__) }
|
22
|
-
it_behaves_like 'download'
|
23
|
-
end
|
24
|
-
|
25
|
-
describe '#file_name' do
|
26
|
-
let(:downloader) { described_class.new(link) }
|
27
|
-
subject { downloader.send(:file_name) }
|
28
|
-
|
29
|
-
context 'when link does not have file name' do
|
30
|
-
let(:link) { 'www.example.com/playlist/abc.mp3' }
|
31
|
-
it { is_expected.to eq 'abc.mp3' }
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'when link have file name' do
|
35
|
-
let(:link) { 'www.example.com/playlist/abc.mp3?filename=abc%20xyz.mp3' }
|
36
|
-
it { is_expected.to eq 'abc xyz.mp3' }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '#file_path' do
|
41
|
-
let(:link) { 'link' }
|
42
|
-
let(:downloader) { described_class.new(link, options) }
|
43
|
-
let(:options) { { folder: folder } }
|
44
|
-
let(:file_name) { 'file_name' }
|
45
|
-
subject { downloader.send(:file_path) }
|
46
|
-
|
47
|
-
before do
|
48
|
-
expect(downloader).to receive(:file_name).and_return(file_name).at_least(:once)
|
49
|
-
end
|
50
|
-
|
51
|
-
context 'when option folder exists' do
|
52
|
-
let(:folder) { 'folder' }
|
53
|
-
it { is_expected.to eq 'folder/file_name' }
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'when option folder does not exist' do
|
57
|
-
let(:folder) { nil }
|
58
|
-
it { is_expected.to eq file_name }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
data/spec/rmd/factory_spec.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RMD::Factory do
|
4
|
-
describe '.build' do
|
5
|
-
let(:factory) { double('RMD::Factory') }
|
6
|
-
let(:link) { 'link' }
|
7
|
-
|
8
|
-
it 'builds adapter' do
|
9
|
-
expect(described_class).to receive(:new).with(link).and_return(factory)
|
10
|
-
expect(factory).to receive(:build)
|
11
|
-
described_class.build(link)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe '#build' do
|
16
|
-
let(:factory) { described_class.new(link) }
|
17
|
-
subject(:result) { factory.build }
|
18
|
-
|
19
|
-
context 'when link belongs to nhaccuatui website' do
|
20
|
-
context 'when link is song link' do
|
21
|
-
let(:link) { 'www.nhaccuatui.com/bai-hat/song.mp3' }
|
22
|
-
|
23
|
-
it 'returns an adapter' do
|
24
|
-
expect(result).to be_a RMD::SongPlaylistAdapter
|
25
|
-
expect(result.song).to be_a RMD::NCT::Song
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context 'when link is playlist link' do
|
30
|
-
let(:link) { 'www.nhaccuatui.com/playlist/bang-kieu' }
|
31
|
-
it { is_expected.to be_a(RMD::NCT::Playlist) }
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'when link belongs to zing website' do
|
36
|
-
context 'when link is song link' do
|
37
|
-
let(:link) { 'mp3.zing.vn/bai-hat/song.mp3' }
|
38
|
-
|
39
|
-
it 'returns an adapter' do
|
40
|
-
expect(result).to be_a RMD::SongPlaylistAdapter
|
41
|
-
expect(result.song).to be_a RMD::Zing::Song
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'when link is playlist link' do
|
46
|
-
let(:link) { 'mp3.zing.vn/playlist/bang-kieu' }
|
47
|
-
it { is_expected.to be_a(RMD::Zing::Playlist) }
|
48
|
-
end
|
49
|
-
|
50
|
-
context 'when link is playlist link' do
|
51
|
-
let(:link) { 'mp3.zing.vn/album/bang-kieu' }
|
52
|
-
it { is_expected.to be_a(RMD::Zing::Playlist) }
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'otherwise' do
|
57
|
-
let(:link) { '' }
|
58
|
-
|
59
|
-
it 'raises errors' do
|
60
|
-
expect { factory.build }.to raise_error
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,140 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RMD::NCT::Getter::KeyFromPage do
|
4
|
-
let(:url) { 'url' }
|
5
|
-
let(:getter) { described_class.new(url) }
|
6
|
-
|
7
|
-
describe '#fetch' do
|
8
|
-
let(:element) { double('Element', text: data_link) }
|
9
|
-
let(:data_link) { 'data_link' }
|
10
|
-
let(:key) { 'key' }
|
11
|
-
let(:errors) { 'The page does not contain the key.' }
|
12
|
-
|
13
|
-
before do
|
14
|
-
allow(getter).to receive(:key).and_return(key)
|
15
|
-
allow(getter).to receive(:element).and_return(element)
|
16
|
-
getter.fetch
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'when key is not present' do
|
20
|
-
let(:key) { nil }
|
21
|
-
|
22
|
-
it 'returns errors' do
|
23
|
-
expect(getter.data_link).to eq nil
|
24
|
-
expect(getter.errors).to eq errors
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context 'when element is not present' do
|
29
|
-
let(:element) { nil }
|
30
|
-
|
31
|
-
it 'returns errors' do
|
32
|
-
expect(getter.data_link).to eq nil
|
33
|
-
expect(getter.errors).to eq errors
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
context 'otherwise' do
|
38
|
-
it 'gets data' do
|
39
|
-
expect(getter.data_link).to eq data_link
|
40
|
-
expect(getter.errors).to eq nil
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe '#response' do
|
46
|
-
let(:body) { '<body>abc</body>' }
|
47
|
-
let(:new_page) { double('Page', body: body) }
|
48
|
-
let(:response) { getter.send(:response).child }
|
49
|
-
|
50
|
-
before do
|
51
|
-
expect(getter).to receive(:new_page).and_return(new_page)
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'parse the response from the page' do
|
55
|
-
expect(response.name).to eq 'body'
|
56
|
-
expect(response.text).to eq 'abc'
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe '#key' do
|
61
|
-
let(:page) { double('Page') }
|
62
|
-
let(:elements) { [element] }
|
63
|
-
let(:element) { double('Element', text: text) }
|
64
|
-
subject { getter.send(:key) }
|
65
|
-
|
66
|
-
before do
|
67
|
-
expect(getter).to receive(:page).and_return(page)
|
68
|
-
expect(page).to receive(:search).with('script').and_return(elements)
|
69
|
-
end
|
70
|
-
|
71
|
-
context 'when match data exists' do
|
72
|
-
let(:text) { 'NCTNowPlaying.intFlashPlayer("flashPlayer", "song", "key");' }
|
73
|
-
it { is_expected.to eq 'key' }
|
74
|
-
end
|
75
|
-
|
76
|
-
context 'when match data is not exists' do
|
77
|
-
let(:text) { 'NCTNowPlaying.initFlashPlayer();' }
|
78
|
-
it { is_expected.to eq nil }
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe '#element' do
|
83
|
-
let(:response) { Nokogiri::XML(xml) }
|
84
|
-
|
85
|
-
before do
|
86
|
-
expect(getter).to receive(:response).and_return(response)
|
87
|
-
end
|
88
|
-
|
89
|
-
context 'when the path exists' do
|
90
|
-
let(:xml) { '<tracklist><location>abc</location></tracklist>' }
|
91
|
-
let(:subject) { getter.send(:element).text }
|
92
|
-
it { is_expected.to eq 'abc' }
|
93
|
-
end
|
94
|
-
|
95
|
-
context 'when the path is not exists' do
|
96
|
-
let(:xml) { '<location>abc</location>' }
|
97
|
-
subject { getter.send(:element) }
|
98
|
-
it { is_expected.to eq nil }
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe '#new_link' do
|
103
|
-
let(:key) { 'key' }
|
104
|
-
subject { getter.send(:new_link) }
|
105
|
-
|
106
|
-
before do
|
107
|
-
expect(getter).to receive(:key).and_return(key)
|
108
|
-
end
|
109
|
-
|
110
|
-
it { is_expected.to eq 'http://www.nhaccuatui.com/flash/xml?key1=key' }
|
111
|
-
end
|
112
|
-
|
113
|
-
describe '#page' do
|
114
|
-
let(:agent) { instance_double('Mechanize') }
|
115
|
-
let(:page) { double('Page') }
|
116
|
-
subject { getter.send(:page) }
|
117
|
-
|
118
|
-
before do
|
119
|
-
expect(getter).to receive(:agent).and_return(agent)
|
120
|
-
expect(agent).to receive(:get).with(url).and_return(page)
|
121
|
-
end
|
122
|
-
|
123
|
-
it { is_expected.to eq page }
|
124
|
-
end
|
125
|
-
|
126
|
-
describe '#new_page' do
|
127
|
-
let(:new_link) { 'new_link' }
|
128
|
-
let(:agent) { instance_double('Mechanize') }
|
129
|
-
let(:page) { double('Page') }
|
130
|
-
subject { getter.send(:new_page) }
|
131
|
-
|
132
|
-
before do
|
133
|
-
expect(getter).to receive(:new_link).and_return(new_link)
|
134
|
-
expect(getter).to receive(:agent).and_return(agent)
|
135
|
-
expect(agent).to receive(:get).with(new_link).and_return(page)
|
136
|
-
end
|
137
|
-
|
138
|
-
it { is_expected.to eq page }
|
139
|
-
end
|
140
|
-
end
|
@@ -1,113 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RMD::NCT::Getter::KeyFromUrl do
|
4
|
-
let(:url) { 'url' }
|
5
|
-
let(:getter) { described_class.new(url) }
|
6
|
-
|
7
|
-
describe '#fetch' do
|
8
|
-
before do
|
9
|
-
expect(getter).to receive(:key).and_return(key)
|
10
|
-
end
|
11
|
-
|
12
|
-
context 'when key is present' do
|
13
|
-
let(:key) { 'key' }
|
14
|
-
let(:stream_url) { 'stream_url' }
|
15
|
-
let(:response) { {
|
16
|
-
'error_message' => error_message,
|
17
|
-
'data' => { 'stream_url' => stream_url }
|
18
|
-
} }
|
19
|
-
|
20
|
-
before do
|
21
|
-
allow(getter).to receive(:response).and_return(response)
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when response is success' do
|
25
|
-
let(:error_message) { 'Success' }
|
26
|
-
|
27
|
-
it 'gets the link' do
|
28
|
-
getter.fetch
|
29
|
-
expect(getter.data_link).to eq stream_url
|
30
|
-
expect(getter.errors).to eq nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'when response is not success' do
|
35
|
-
let(:error_message) { 'error_message' }
|
36
|
-
let(:new_link) { 'new_link' }
|
37
|
-
|
38
|
-
before do
|
39
|
-
expect(getter).to receive(:new_link).and_return(new_link)
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'returns errors' do
|
43
|
-
getter.fetch
|
44
|
-
expect(getter.data_link).to eq nil
|
45
|
-
expect(getter.errors).to eq 'error_message: new_link'
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context 'when key is not present' do
|
51
|
-
let(:key) { nil }
|
52
|
-
|
53
|
-
it 'returns errors' do
|
54
|
-
getter.fetch
|
55
|
-
expect(getter.data_link).to eq nil
|
56
|
-
expect(getter.errors).to eq 'The url does not contain the key.'
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe '#response' do
|
62
|
-
let(:page) { double('Page', body: body) }
|
63
|
-
let(:body) { "{\"abc\":\"xyz\"}" }
|
64
|
-
let(:response) { { 'abc' => 'xyz' } }
|
65
|
-
subject { getter.send(:response) }
|
66
|
-
|
67
|
-
before do
|
68
|
-
expect(getter).to receive(:page).and_return(page)
|
69
|
-
end
|
70
|
-
|
71
|
-
it { is_expected.to eq response }
|
72
|
-
end
|
73
|
-
|
74
|
-
describe '#key' do
|
75
|
-
subject { getter.send(:key) }
|
76
|
-
|
77
|
-
context 'when there is no match' do
|
78
|
-
let(:url) { 'http://www.nhaccuatui.com/bai-hat/the-clockmaker-vexare.html' }
|
79
|
-
it { is_expected.to eq nil }
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'when there is a match' do
|
83
|
-
let(:url) { 'http://www.nhaccuatui.com/bai-hat/the-clockmaker-vexare.eorOqCpY7k46.html' }
|
84
|
-
it { is_expected.to eq 'eorOqCpY7k46' }
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe '#new_link' do
|
89
|
-
let(:key) { 'key' }
|
90
|
-
subject { getter.send(:new_link) }
|
91
|
-
|
92
|
-
before do
|
93
|
-
expect(getter).to receive(:key).and_return(key)
|
94
|
-
end
|
95
|
-
|
96
|
-
it { is_expected.to eq 'http://www.nhaccuatui.com/download/song/key' }
|
97
|
-
end
|
98
|
-
|
99
|
-
describe '#page' do
|
100
|
-
let(:new_link) { 'new_link' }
|
101
|
-
let(:agent) { instance_double('Mechanize') }
|
102
|
-
let(:page) { double('Page') }
|
103
|
-
subject { getter.send(:page) }
|
104
|
-
|
105
|
-
before do
|
106
|
-
expect(getter).to receive(:new_link).and_return(new_link)
|
107
|
-
expect(getter).to receive(:agent).and_return(agent)
|
108
|
-
expect(agent).to receive(:get).with(new_link).and_return(page)
|
109
|
-
end
|
110
|
-
|
111
|
-
it { is_expected.to eq page }
|
112
|
-
end
|
113
|
-
end
|