xiami_sauce 0.0.1 → 0.0.2

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
+ SHA1:
3
+ metadata.gz: ca6f3d6701281dfc430d2fd2f17bdb58dc622c92
4
+ data.tar.gz: 97b99e4e6a7d83017b026415bf0ed1641cf6db5f
5
+ SHA512:
6
+ metadata.gz: 0831a00e09656a48b0d1b5619889c3c1f48e9a5960c994d8a337ee7307aeba267100ee2cabc8ee84b6e051aaeb67ffd6f0237bb1890d985b0903cd5f743f376b
7
+ data.tar.gz: 92ee592a6ecd6256f04d9907d760c5cf1f7f2bef11299467338deaaa4d0da58fde895c79d005dac83ca7d61db6129196f06d1d69094659462f32b2676324f48e
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - jruby
6
+ script: "bundle exec rake spec"
data/Gemfile CHANGED
@@ -1,4 +1,15 @@
1
- source 'https://rubygems.org'
1
+ source 'http://ruby.taobao.org'
2
+ # source 'https://rubygems.org'
2
3
 
3
- # Specify your gem's dependencies in xiami_sauce.gemspec
4
4
  gemspec
5
+
6
+ gem 'guard'
7
+ gem 'guard-bundler'
8
+ gem 'guard-rspec'
9
+
10
+ gem 'rb-fsevent', '>= 0.3.9'
11
+ gem 'rb-inotify', '>= 0.5.1'
12
+
13
+ # Notification System
14
+ gem 'terminal-notifier-guard', require: RUBY_PLATFORM.downcase.include?("darwin") ? 'terminal-notifier-guard' : nil
15
+ gem 'libnotify', require: RUBY_PLATFORM.downcase.include?("linux") ? 'libnotify' : nil
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ RVM_PREFIX = "env -u RUBYOPT rvm 1.8.7,1.9.3-p327,2.0.0 do"
2
+ BUNDLE_CMD = lambda { puts "Bundling gems..."; puts `#{RVM_PREFIX} bundle install` }
3
+
4
+ guard 'bundler' do
5
+ watch(/^.+\.gemspec/, &BUNDLE_CMD)
6
+ watch('Gemfile', &BUNDLE_CMD)
7
+ end
8
+
9
+ guard 'rspec', cli: "--color --format documentation" do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
data/README.md CHANGED
@@ -1,29 +1,46 @@
1
- # XiamiSauce
1
+ # 虾米酱 - XiamiSauce
2
2
 
3
- TODO: Write a gem description
3
+ [![Gem Version](https://badge.fury.io/rb/xiami_sauce.png)](http://badge.fury.io/rb/xiami_sauce)
4
+ [![Build Status](https://travis-ci.org/ranmocy/xiami_sauce.png)](https://travis-ci.org/ranmocy/xiami_sauce)
5
+ [![Dependency Status](https://gemnasium.com/ranmocy/xiami_sauce.png)](https://gemnasium.com/ranmocy/xiami_sauce)
6
+ [![Code Climate](https://codeclimate.com/github/ranmocy/xiami_sauce.png)](https://codeclimate.com/github/ranmocy/xiami_sauce)
4
7
 
5
- ## Installation
8
+ 虾米酱是一个虾米音乐下载器。封装成为一个 Ruby Gem 包。
6
9
 
7
- Add this line to your application's Gemfile:
10
+ XiamiSauce is a downloader of Xiami Music. Writed in Ruby, and presented as a Gem.
8
11
 
9
- gem 'xiami_sauce'
12
+ ## Why
10
13
 
11
- And then execute:
14
+ You know, if you know it.
12
15
 
13
- $ bundle
16
+ ## 依赖 - Dependency
14
17
 
15
- Or install it yourself as:
18
+ 虾米酱在 Ruby 1.9.2, 1.9.3, 2.0.0, jRuby, REE 环境下测试。
19
+ XiamiSauce will be tested under Ruby 1.9.2, 1.9.3, 2.0.0, jRuby, REE.
16
20
 
17
- $ gem install xiami_sauce
21
+ 依赖 Thor, Nokogiri 的 Gem 包。
22
+ Depend on Gems Thor and Nokogiri.
18
23
 
19
- ## Usage
24
+ ## 安装 - Installation
20
25
 
21
- TODO: Write usage instructions here
26
+ 一句话安装 - Install it with one-line code:
22
27
 
23
- ## Contributing
28
+ $ gem install xiami_sauce --no-ri --no-doc
24
29
 
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
30
+ ## 使用方法 - Usage
31
+
32
+ $ xsauce http://www.xiami.com/artist/64360
33
+ $ xsauce http://www.xiami.com/album/355791
34
+ $ xsauce http://www.xiami.com/song/184616
35
+
36
+ 虾米酱会按照歌曲信息下载到 `[artist]/[album]/[index].[song].mp3`。
37
+
38
+ XiamiSauce will download to `[artist]/[album]/[index].[song].mp3`.
39
+
40
+ ## 参与 - Contributing
41
+
42
+ 1. 派生 - Fork it
43
+ 2. 新建特性分支 - Create your feature branch (`git checkout -b my-new-feature`)
44
+ 3. 提交你的修改 - Commit your changes (`git commit -am 'Add some feature'`)
45
+ 4. 推送特性分支 - Push to the branch (`git push origin my-new-feature`)
46
+ 5. 发起合并请求 - Create new Pull Request
data/Rakefile CHANGED
@@ -1 +1,32 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ # Rspec tasks
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ # Version tasks
8
+ require 'rake/version_task'
9
+ Rake::VersionTask.new
10
+
11
+ # include Rake::DSL if defined?(Rake::DSL)
12
+
13
+ RVM_PREFIX = "rvm 1.8.7,1.9.3-p327,2.0.0 do"
14
+
15
+
16
+ namespace :spec do
17
+ desc "Run on three Rubies"
18
+ task :platforms do
19
+ exit $?.exitstatus unless system "#{RVM_PREFIX} bundle install"
20
+ exit $?.exitstatus unless system "#{RVM_PREFIX} bundle exec rake spec"
21
+ end
22
+ end
23
+
24
+ task default: 'spec:platforms'
25
+
26
+ desc 'Push everywhere!'
27
+ task :publish do
28
+ system %{git push github}
29
+ system %{git push github --tags}
30
+ system %{git push gitcafe}
31
+ system %{git push gitcafe --tags}
32
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
data/bin/xsauce ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require "xiami_sauce"
5
+ rescue
6
+ require "rubygems"
7
+ require "xiami_sauce"
8
+ end
9
+
10
+ XiamiSauce::CLI.start
@@ -0,0 +1,23 @@
1
+ require 'thor'
2
+
3
+ module XiamiSauce
4
+ class CLI < Thor
5
+ default_task :download
6
+
7
+ desc 'download URL', 'download the music from a page url.'
8
+ def download(url=nil)
9
+ unless url
10
+ puts "Target Xiami URL[Song, Album, Artist, ShowCollect]:"
11
+ url = gets.chomp
12
+ end
13
+ puts "Preparing to download #{url}."
14
+
15
+ list = TrackList.new(url).download
16
+ end
17
+
18
+ def method_missing(url, *args)
19
+ download(url)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,68 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+
4
+ module XiamiSauce
5
+ class Downloader
6
+ RETRY_TIMES = 3
7
+ SLEEP_TIME = 3
8
+
9
+ attr_accessor :url, :file
10
+
11
+ def initialize(url, file)
12
+ @url = url
13
+ @file = file
14
+ end
15
+
16
+ def download
17
+ FileUtils.mkdir_p(@file.parent) unless @file.parent.exist?
18
+
19
+ puts "Downloading #{@file}."
20
+ return puts 'Skip.'.color(:yellow) if @file.exist?
21
+
22
+ retry_count = RETRY_TIMES
23
+ begin
24
+ raise unless(download_file url, @file)
25
+ rescue Exception => e
26
+ if retry_count == 0
27
+ puts 'Failed.'.color(:red)
28
+ else
29
+ puts "Retry remain #{retry_count -= 1} times.".color(:yellow)
30
+ sleep(SLEEP_TIME)
31
+ retry
32
+ end
33
+ end
34
+
35
+ puts 'Done.'.color(:green)
36
+ sleep(SLEEP_TIME)
37
+ end
38
+
39
+ def check_file file_path
40
+ /MPEG/.match(`file -b \"#{file_path}\"`)
41
+ end
42
+
43
+ def check_downloader
44
+ return :curl if system('which curl >/dev/null')
45
+ return :wget if system('which wget >/dev/null')
46
+ raise 'No available downloader, currently support curl and wget.'
47
+ end
48
+
49
+ def download_file url, filename=nil
50
+ puts "[Debug] DownloadFile::Params #{url}, #{filename}" if $DEBUG
51
+
52
+ remote = url && url.to_s.gsub("\"", "\\\\\"")
53
+ local = filename && filename.to_s.gsub("\"", "\\\\\"")
54
+ puts "[Debug] DownloadFile::Prepare #{remote}, #{local}" if $DEBUG
55
+
56
+ case check_downloader
57
+ when :curl
58
+ command = local ? ("curl -\# \"%s\" > \"%s\"" % [remote, local]) : ("curl -O %s" % remote)
59
+ when :wget
60
+ command = local ? ("wget -O \"%s\" \"%s\"" % [local, remote]) : ("wget %s" % remote)
61
+ end
62
+
63
+ puts "[Debug] DownloadFile: #{command}" if $DEBUG
64
+ system(command) && check_file(local)
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,105 @@
1
+ require "cgi"
2
+ require 'net/http'
3
+ require 'nokogiri'
4
+ require_relative 'downloader'
5
+
6
+ module XiamiSauce
7
+ class Track
8
+ attr_accessor :id, :index, :name, :location, :url
9
+ attr_accessor :album_id, :album_cover, :album_name
10
+ attr_accessor :artist_id, :artist_name
11
+ # user_id is who use the widget, could be 0.
12
+ # attr_accessor :user_id, :width, :height, :widgetCode
13
+
14
+ # @todo I wish index could be fetch automatically from somewhere.
15
+ def initialize(song_url, index=nil)
16
+ @id = song_url.match(/song\/([0-9]+)/)[1]
17
+ @index = index.to_s
18
+
19
+ parse_info
20
+ end
21
+
22
+ def download(parent_path=nil)
23
+ file = Pathname('.').join((parent_path || album_name), url.split('/').last)
24
+ @downloader = Downloader.new(url, file)
25
+ @downloader.download
26
+ end
27
+
28
+ def file_name
29
+ index_string = index ? index.to_s.rjust(2, '0') + '.' : ''
30
+ "[#{artist_name}-#{album_name}]#{index_string}#{name}.mp3"
31
+ end
32
+
33
+ def info_src
34
+ @info_src ||= "http://www.xiami.com/widget/xml-single/uid/0/sid/#{id}"
35
+ end
36
+
37
+
38
+ private
39
+
40
+ def parse_info
41
+ url_str = URI.parse(info_src)
42
+ site = Net::HTTP.new(url_str.host, url_str.port)
43
+ xml = site.get2(url_str.path,{'accept'=>'text/html'}).body
44
+ doc = Nokogiri::XML(xml)
45
+
46
+ doc.css('track *').each do |element|
47
+ instance_variable_set("@#{element.name}", element.content)
48
+ end
49
+ @name = @song_name
50
+ @url = sospa(@location)
51
+ end
52
+
53
+ def sospa(location)
54
+ totle = location.to_i
55
+ new_str = location[1..-1]
56
+ chu = (new_str.length.to_f / totle).floor
57
+ yu = new_str.length % totle
58
+ stor = []
59
+
60
+ i = 0
61
+ while i < yu do
62
+ index = (chu+1)*i
63
+ length = chu+1
64
+ stor[i] = new_str[index...index+length]
65
+
66
+ i+=1
67
+ end
68
+
69
+
70
+ i = yu
71
+ while i < totle do
72
+ index = chu*(i-yu)+(chu+1)*yu
73
+ length = chu
74
+
75
+ stor[i] = new_str[index...index+length]
76
+
77
+ i+=1
78
+ end
79
+
80
+ pin_str = ""
81
+ 0.upto(stor[0].length-1) do |ii|
82
+ 0.upto(stor.length-1) do |jj|
83
+ pin_str += stor[jj][ii...ii+1]
84
+ end
85
+ end
86
+
87
+ pin_str = rtan(pin_str)
88
+ return_str = ""
89
+
90
+ 0.upto(pin_str.length-1) do |iii|
91
+ if pin_str[iii...iii+1]=='^'
92
+ return_str<<"0"
93
+ else
94
+ return_str<<pin_str[iii...iii+1]
95
+ end
96
+ end
97
+
98
+ return_str
99
+ end
100
+
101
+ def rtan(str)
102
+ CGI::unescape(str)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,85 @@
1
+ require 'pathname'
2
+ require_relative 'track'
3
+ require 'nokogiri'
4
+
5
+ module XiamiSauce
6
+ class URLParseError < StandardError; end
7
+ class DocParseError < StandardError; end
8
+ class InvalidURLType < StandardError; end
9
+
10
+ class TrackList
11
+ SONG_SELECTOR = nil
12
+ ALBUM_SELECTOR = "div#track.album_tracks table.track_list tr td.song_name"
13
+ ARTIST_SELECTOR = "div#artist_trends table.track_list td.song_name"
14
+ SHOWCOLLECT_SELECTOR = "div#list_collect div.quote_song_list li span.song_name"
15
+
16
+ attr_accessor :list
17
+
18
+ def initialize(url=nil)
19
+ @list = []
20
+ parse(url) if url
21
+ end
22
+
23
+ def parse(url)
24
+ @uri, @type = parse_url(url)
25
+ @doc = parse_doc(@uri)
26
+ urls = parse_info_from_doc(selector(@type))
27
+ @list += urls.collect { |url| Track.new(url) }
28
+ self
29
+ end
30
+
31
+ def download(target_path=nil)
32
+ path = (target_path && Pathname.new(target_path.to_s).exists?) || Pathname.new("./")
33
+
34
+ puts "Downloading #{@list.size} tracks..."
35
+ count = @list.uniq.inject(0) do |count, track|
36
+ count += 1 if track.download
37
+ end
38
+ puts "Downloaded #{count}/#{@list.size} tracks."
39
+ count
40
+ end
41
+
42
+
43
+ def to_a
44
+ @list
45
+ end
46
+
47
+ def method_missing(method_name, *args)
48
+ @list.send(method_name, *args)
49
+ self
50
+ end
51
+
52
+
53
+ private
54
+
55
+ def parse_url(url)
56
+ uri = URI.parse(url)
57
+ type = uri.path.split('/')[1].to_sym
58
+ [uri, type]
59
+ rescue Exception => e
60
+ raise URLParseError, e.message
61
+ end
62
+
63
+ def parse_doc(uri)
64
+ site = Net::HTTP.new(uri.host, uri.port)
65
+ xml = site.get2(uri.path, {'accept' => 'text/html', 'user-agent' => 'Mozilla/5.0'}).body
66
+ Nokogiri::HTML(xml)
67
+ rescue Exception => e
68
+ raise DocParseError, e.message
69
+ end
70
+
71
+ def parse_info_from_doc(selector)
72
+ return [@uri.to_s] unless selector
73
+ @doc.css(selector).collect { |element| element.css("a").first["href"] }
74
+ end
75
+
76
+ def selector(type)
77
+ selector_name = "#{type.to_s.upcase}_SELECTOR"
78
+ unless self.class.const_defined?(selector_name)
79
+ raise InvalidURLType, "#{type} isn't a supported URL type. Check your URL."
80
+ end
81
+ self.class.const_get(selector_name)
82
+ end
83
+
84
+ end
85
+ end
data/lib/xiami_sauce.rb CHANGED
@@ -1,5 +1,8 @@
1
- require "xiami_sauce/version"
1
+ require 'rainbow'
2
+ require 'xiami_sauce/downloader'
3
+ require 'xiami_sauce/track'
4
+ require 'xiami_sauce/track_list'
5
+ require 'xiami_sauce/cli'
2
6
 
3
7
  module XiamiSauce
4
- # Your code goes here...
5
8
  end
@@ -0,0 +1,7 @@
1
+ require "mocha/api"
2
+
3
+ RSpec.configure do |c|
4
+ c.mock_with :mocha
5
+ end
6
+
7
+ require 'xiami_sauce'
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ describe XiamiSauce::Downloader do
4
+
5
+ end
@@ -0,0 +1,82 @@
1
+ require "spec_helper"
2
+
3
+ # should define :subject as TrackList
4
+ shared_context "parse to doc" do |url|
5
+ before(:all) do
6
+ track_list = XiamiSauce::TrackList.new
7
+ @uri, @type = track_list.send(:parse_url, url)
8
+ track_list.instance_variable_set("@uri", @uri)
9
+ track_list.instance_variable_set("@type", @type)
10
+ sleep(2)
11
+ @doc = track_list.send(:parse_doc, @uri)
12
+ end
13
+ before(:each) do
14
+ subject { XiamiSauce::TrackList.new }
15
+ subject.instance_variable_set("@doc", @doc)
16
+ # subject.stubs(:parse_doc).returns(@doc)
17
+ end
18
+ end
19
+
20
+ # should define :subject as TrackList
21
+ shared_examples "a right parser" do |type, expected_result|
22
+ let(:selector) { subject.send(:selector, type) }
23
+ let(:parse_result) { subject.send(:parse_info_from_doc, selector) }
24
+ it { expect(parse_result).to be_kind_of Array }
25
+ it { expect(parse_result.first).to be_kind_of String }
26
+ it { expect(parse_result.size).to be == expected_result }
27
+ end
28
+
29
+ describe XiamiSauce::TrackList do
30
+ context "to parse doc" do
31
+ let(:url) { 'http://www.xiami.com/song/1770450682' }
32
+ subject { XiamiSauce::TrackList.new }
33
+
34
+ it "should parse url" do
35
+ uri, type = subject.send(:parse_url, url)
36
+ uri.path.should == '/song/1770450682'
37
+ type.should == :song
38
+ end
39
+
40
+ it "should parse doc" do
41
+ uri, type = subject.send(:parse_url, url)
42
+ subject.instance_variable_set("@uri", uri)
43
+ subject.instance_variable_set("@type", type)
44
+ doc = subject.send(:parse_doc, uri)
45
+ subject.instance_variable_set("@doc", doc)
46
+ subject.instance_variable_get("@doc").should be_kind_of Nokogiri::HTML::Document
47
+ end
48
+ end
49
+
50
+
51
+ context "should support type song" do
52
+ include_context "parse to doc", 'http://www.xiami.com/song/1770450682'
53
+ it_should_behave_like "a right parser", "song", 1
54
+ end
55
+
56
+ context "should support type album" do
57
+ include_context "parse to doc", 'http://www.xiami.com/album/462525'
58
+ it_should_behave_like "a right parser", "album", 7
59
+ end
60
+
61
+ context "should support type artist" do
62
+ include_context "parse to doc", 'http://www.xiami.com/artist/19775'
63
+ it_should_behave_like "a right parser", "artist", 10
64
+ end
65
+
66
+ context "should support type showcollect" do
67
+ include_context "parse to doc", 'http://www.xiami.com/song/showcollect/id/10100776'
68
+ it_should_behave_like "a right parser", "showcollect", 50
69
+ end
70
+
71
+
72
+ context "doing operations" do
73
+ let(:a_url) { 'http://www.xiami.com/album/355791' }
74
+ let(:a_list) { XiamiSauce::TrackList.new(a_url) }
75
+ let(:b_url) { 'http://www.xiami.com/album/362997' }
76
+ let(:b_list) { XiamiSauce::TrackList.new(b_url) }
77
+
78
+ it "should be able to add" do
79
+ (a_list << b_list).list.should be == (a_list.list << b_list.list)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe XiamiSauce::Track do
4
+ let(:song_url) { "http://www.xiami.com/song/1770361274" }
5
+ let(:index) { 9 }
6
+
7
+ subject { XiamiSauce::Track.new(song_url, index) }
8
+
9
+ its('id') { should == '1770361274' }
10
+ its('index') { should == '9' }
11
+ its('name') { should == 'Kids (Unedited Version)' }
12
+ its('url') { should == 'http://f1.xiami.net/11768/454588/02_1770361274_2491919.mp3' }
13
+ its('album_id') { should == '454588' }
14
+ its('album_cover') { should == 'http://img.xiami.com/./images/album/img68/11768/4545881311563810_3.jpg' }
15
+ its('album_name') { should == 'The Way I Am' }
16
+ its('artist_id') { should == '11768' }
17
+ its('artist_name') { should == 'Eminem' }
18
+
19
+ its('file_name') { should == '[Eminem-The Way I Am]09.Kids (Unedited Version).mp3' }
20
+ end
data/xiami_sauce.gemspec CHANGED
@@ -1,16 +1,14 @@
1
- # coding: utf-8
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'xiami_sauce/version'
5
3
 
6
4
  Gem::Specification.new do |spec|
7
5
  spec.name = "xiami_sauce"
8
- spec.version = XiamiSauce::VERSION
6
+ spec.version = File.open('VERSION') { |f| f.read }
9
7
  spec.authors = ["Wanzhang Sheng"]
10
8
  spec.email = ["ranmocy@gmail.com"]
11
9
  spec.description = %q{A Xiami Downloader.}
12
10
  spec.summary = %q{A Xiami Downloader.}
13
- spec.homepage = ""
11
+ spec.homepage = "http://ranmocy.github.com/xiami_sauce"
14
12
  spec.license = "MIT"
15
13
 
16
14
  spec.files = `git ls-files`.split($/)
@@ -18,6 +16,13 @@ Gem::Specification.new do |spec|
18
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
17
  spec.require_paths = ["lib"]
20
18
 
19
+ spec.add_dependency 'thor', '~> 0.17.0'
20
+ spec.add_dependency 'nokogiri', '~> 1.5.0'
21
+ spec.add_dependency 'rainbow', '~> 1.1.0'
22
+
21
23
  spec.add_development_dependency "bundler", "~> 1.3"
22
24
  spec.add_development_dependency "rake"
25
+ spec.add_development_dependency 'version'
26
+ spec.add_development_dependency 'rspec'
27
+ spec.add_development_dependency 'mocha', '~> 0.13.0'
23
28
  end
metadata CHANGED
@@ -1,92 +1,180 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xiami_sauce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 0.0.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Wanzhang Sheng
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-03-11 00:00:00.000000000 Z
11
+ date: 2013-03-17 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.17.0
20
+ type: :runtime
15
21
  prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.17.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 1.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rainbow
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 1.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.1.0
55
+ - !ruby/object:Gem::Dependency
16
56
  name: bundler
17
57
  requirement: !ruby/object:Gem::Requirement
18
58
  requirements:
19
59
  - - ~>
20
60
  - !ruby/object:Gem::Version
21
61
  version: '1.3'
22
- none: false
23
62
  type: :development
63
+ prerelease: false
24
64
  version_requirements: !ruby/object:Gem::Requirement
25
65
  requirements:
26
66
  - - ~>
27
67
  - !ruby/object:Gem::Version
28
68
  version: '1.3'
29
- none: false
30
69
  - !ruby/object:Gem::Dependency
31
- prerelease: false
32
70
  name: rake
33
71
  requirement: !ruby/object:Gem::Requirement
34
72
  requirements:
35
- - - ! '>='
73
+ - - '>='
36
74
  - !ruby/object:Gem::Version
37
75
  version: '0'
38
- none: false
39
76
  type: :development
77
+ prerelease: false
40
78
  version_requirements: !ruby/object:Gem::Requirement
41
79
  requirements:
42
- - - ! '>='
80
+ - - '>='
43
81
  - !ruby/object:Gem::Version
44
82
  version: '0'
45
- none: false
83
+ - !ruby/object:Gem::Dependency
84
+ name: version
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: mocha
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.13.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 0.13.0
46
125
  description: A Xiami Downloader.
47
126
  email:
48
127
  - ranmocy@gmail.com
49
- executables: []
128
+ executables:
129
+ - xsauce
50
130
  extensions: []
51
131
  extra_rdoc_files: []
52
132
  files:
53
133
  - .gitignore
134
+ - .travis.yml
54
135
  - Gemfile
136
+ - Guardfile
55
137
  - LICENSE.txt
56
138
  - README.md
57
139
  - Rakefile
140
+ - VERSION
141
+ - bin/xsauce
58
142
  - lib/xiami_sauce.rb
59
- - lib/xiami_sauce/version.rb
143
+ - lib/xiami_sauce/cli.rb
144
+ - lib/xiami_sauce/downloader.rb
145
+ - lib/xiami_sauce/track.rb
146
+ - lib/xiami_sauce/track_list.rb
147
+ - spec/spec_helper.rb
148
+ - spec/xiami_sauce/downloader_spec.rb
149
+ - spec/xiami_sauce/track_list_spec.rb
150
+ - spec/xiami_sauce/track_spec.rb
60
151
  - xiami_sauce.gemspec
61
- homepage: ''
152
+ homepage: http://ranmocy.github.com/xiami_sauce
62
153
  licenses:
63
154
  - MIT
155
+ metadata: {}
64
156
  post_install_message:
65
157
  rdoc_options: []
66
158
  require_paths:
67
159
  - lib
68
160
  required_ruby_version: !ruby/object:Gem::Requirement
69
161
  requirements:
70
- - - ! '>='
162
+ - - '>='
71
163
  - !ruby/object:Gem::Version
72
- segments:
73
- - 0
74
164
  version: '0'
75
- hash: -3039331413833145677
76
- none: false
77
165
  required_rubygems_version: !ruby/object:Gem::Requirement
78
166
  requirements:
79
- - - ! '>='
167
+ - - '>='
80
168
  - !ruby/object:Gem::Version
81
- segments:
82
- - 0
83
169
  version: '0'
84
- hash: -3039331413833145677
85
- none: false
86
170
  requirements: []
87
171
  rubyforge_project:
88
- rubygems_version: 1.8.25
172
+ rubygems_version: 2.0.0
89
173
  signing_key:
90
- specification_version: 3
174
+ specification_version: 4
91
175
  summary: A Xiami Downloader.
92
- test_files: []
176
+ test_files:
177
+ - spec/spec_helper.rb
178
+ - spec/xiami_sauce/downloader_spec.rb
179
+ - spec/xiami_sauce/track_list_spec.rb
180
+ - spec/xiami_sauce/track_spec.rb
@@ -1,3 +0,0 @@
1
- module XiamiSauce
2
- VERSION = "0.0.1"
3
- end