bremen 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bremen.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ notification :off
2
+ guard 'minitest' do
3
+ watch(%r|^spec/(.*)_spec\.rb|)
4
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
5
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
6
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 itzki
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Bremen
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'bremen'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install bremen
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
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
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ #t.libs.push 'lib'
6
+ t.test_files = FileList['spec/**/*_spec.rb']
7
+ t.verbose = true
8
+ end
data/bremen.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bremen/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "bremen"
8
+ gem.version = Bremen::VERSION
9
+ gem.authors = ["itzki"]
10
+ gem.email = ["itzki.h@gmail.com"]
11
+ gem.description = %q{integrated searcher of audio track on music sites}
12
+ gem.summary = %q{integrated searcher of audio track on music sites}
13
+ gem.homepage = "https://github.com/itzki/bremen"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency 'guard-minitest', ['>= 0']
21
+ gem.add_development_dependency 'rb-fsevent', ['>= 0']
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'bremen/track'
2
+ require 'bremen/request'
3
+
4
+ module Bremen
5
+ class Base
6
+ include Track
7
+ extend Request
8
+
9
+ class << self
10
+ attr_accessor :default_options
11
+
12
+ def find options = {}
13
+ convert_from_response(get(search_url(options)))
14
+ end
15
+
16
+ #abstract methods
17
+ def search_url options = {}; end
18
+ private
19
+ def convert_from_response response; end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ require 'json'
2
+ require 'bremen/base'
3
+
4
+ module Bremen
5
+ class Mixcloud < Bremen::Base
6
+ BASE_URL = 'http://api.mixcloud.com/search/'
7
+ self.default_options = {
8
+ keyword: '',
9
+ limit: 20,
10
+ }
11
+
12
+ class << self
13
+ def search_url options = {}
14
+ options = default_options.merge(options)
15
+ query = {
16
+ q: options[:keyword],
17
+ limit: options[:limit],
18
+ type: 'cloudcast',
19
+ }
20
+ "#{BASE_URL}?#{build_query(query)}"
21
+ end
22
+
23
+ def from_api hash = {}
24
+ created_at = Time.parse(hash['created_time'])
25
+ new({
26
+ uid: hash['key'],
27
+ url: hash['url'],
28
+ title: hash['name'],
29
+ author: hash['user']['name'],
30
+ length: hash['audio_length'].to_i,
31
+ created_at: created_at,
32
+ updated_at: created_at,
33
+ })
34
+ end
35
+
36
+ private
37
+ def convert_from_response response
38
+ JSON.parse(response)['data'].map{|t| from_api(t) }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ require 'json'
2
+ require 'bremen/base'
3
+
4
+ module Bremen
5
+ class Nicovideo < Bremen::Base
6
+ BASE_URL = 'http://www.nicovideo.jp/search/'
7
+ self.default_options = {
8
+ keyword: '',
9
+ sort: 'f', #n(newer commented)/v(viewed)/r(most commented)/m(listed)/f(uploaded)/l(duration)
10
+ order: 'd', #a(asc)/d(desc)
11
+ within: '', #1(24h)/2(1w)/3(1m)
12
+ length: '', #1(-5min)/2(20min-)
13
+ downloadable: '', #1(music downloadable)
14
+ }
15
+
16
+ class << self
17
+ def search_url options = {}
18
+ options = default_options.merge(options)
19
+ query = {
20
+ sort: options[:sort],
21
+ order: options[:order],
22
+ f_range: options[:within],
23
+ l_range: options[:length],
24
+ opt_md: options[:downloadable],
25
+ }
26
+ "#{BASE_URL}#{CGI.escape(options[:keyword])}?#{build_query(query)}"
27
+ end
28
+
29
+ private
30
+ def convert_from_response response
31
+ response.scan(%r{<div class="thumb_col_1">\n<!---->\n(.*?)\n<!---->\n</div></div>}m).flatten.map do |html|
32
+ uid = html.scan(%r{<table [^>]+ summary="(.+)">}).flatten.first
33
+ min, sec = html.scan(%r{<p class="vinfo_length"><span>([\d:]+)</span></p>}).flatten.first.to_s.split(':')
34
+ created_at = Time.parse(html.scan(%r{<strong>(.+:\d\d)</strong>}).flatten.first.to_s.gsub(/\xE5\xB9\xB4|\xE6\x9C\x88|\xE6\x97\xA5/, ''))
35
+ new({
36
+ uid: uid,
37
+ url: "http://www.nicovideo.jp/watch/#{uid}",
38
+ title: CGI.unescape(html.scan(%r{<a [^>]+ class="watch" [^>]+>(.+)</a>}).flatten.first.to_s),
39
+ length: min.to_i * 60 + sec.to_i,
40
+ created_at: created_at,
41
+ updated_at: created_at,
42
+ })
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,14 @@
1
+ require 'open-uri'
2
+ require 'cgi'
3
+
4
+ module Bremen
5
+ module Request
6
+ def get url
7
+ open(url).read
8
+ end
9
+
10
+ def build_query options = {}
11
+ options.to_a.map{|o| "#{o[0]}=#{CGI.escape(o[1].to_s)}" }.join('&')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ require 'json'
2
+ require 'bremen/base'
3
+
4
+ module Bremen
5
+ class Soundcloud < Bremen::Base
6
+ BASE_URL = 'http://api.soundcloud.com/tracks.json'
7
+ self.default_options = {
8
+ keyword: '',
9
+ order: 'created_at', #created_at/hotness
10
+ limit: 50,
11
+ filter: '', #(all)/public/private/streamable/downloadable
12
+ }
13
+
14
+ class << self
15
+ attr_accessor :consumer_key
16
+
17
+ def search_url options = {}
18
+ raise %Q{"#{self.name}.consumer_key" must be set} unless consumer_key
19
+ options = default_options.merge(options)
20
+ query = {
21
+ q: options[:keyword],
22
+ order: options[:order],
23
+ limit: options[:limit],
24
+ filter: options[:filter],
25
+ consumer_key: consumer_key,
26
+ }
27
+ "#{BASE_URL}?#{build_query(query)}"
28
+ end
29
+
30
+ def from_api hash = {}
31
+ new({
32
+ uid: hash['id'],
33
+ url: hash['permalink_url'],
34
+ title: hash['title'],
35
+ author: hash['user']['username'],
36
+ length: (hash['duration'].to_i / 1000).round,
37
+ created_at: Time.parse(hash['created_at']),
38
+ updated_at: Time.parse(hash['created_at']),
39
+ })
40
+ end
41
+
42
+ private
43
+ def convert_from_response response
44
+ JSON.parse(response).map{|t| from_api(t) }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ module Bremen
2
+ module Track
3
+ attr_accessor :uid, :url, :title, :author, :length, :created_at, :updated_at
4
+
5
+ def initialize attrs = {}
6
+ attrs.each do |key, value|
7
+ send("#{key}=", value) if respond_to?(key)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Bremen
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,45 @@
1
+ require 'json'
2
+ require 'bremen/base'
3
+
4
+ module Bremen
5
+ class Youtube < Bremen::Base
6
+ BASE_URL = 'http://gdata.youtube.com/feeds/api/videos/'
7
+ self.default_options = {
8
+ order: 'published', #relevance/published/viewCount/rating
9
+ limit: 25,
10
+ category: 'Music',
11
+ tag: '',
12
+ }
13
+
14
+ class << self
15
+ def search_url options = {}
16
+ options = default_options.merge(options)
17
+ query = {
18
+ vq: options[:keyword],
19
+ orderby: options[:order],
20
+ :"max-results" => options[:limit],
21
+ alt: 'json',
22
+ }
23
+ "#{BASE_URL}-/#{options[:category]}/#{options[:tag]}/?#{build_query(query)}"
24
+ end
25
+
26
+ def from_api hash = {}
27
+ uid = hash['id']['$t'].sub('http://gdata.youtube.com/feeds/api/videos/', '')
28
+ new({
29
+ uid: uid,
30
+ url: "http://www.youtube.com/watch?v=#{uid}",
31
+ title: hash['title']['$t'],
32
+ author: hash['author'].first['name']['$t'],
33
+ length: hash['media$group']['yt$duration']['seconds'].to_i,
34
+ created_at: Time.parse(hash['published']['$t']),
35
+ updated_at: Time.parse(hash['updated']['$t']),
36
+ })
37
+ end
38
+
39
+ private
40
+ def convert_from_response response
41
+ JSON.parse(response)['feed']['entry'].map{|t| from_api(t) }
42
+ end
43
+ end
44
+ end
45
+ end
data/lib/bremen.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'bremen/version'
2
+ require 'bremen/youtube'
3
+ require 'bremen/soundcloud'
4
+ require 'bremen/mixcloud'
5
+ require 'bremen/nicovideo'
6
+
7
+ module Bremen
8
+ end
@@ -0,0 +1,29 @@
1
+ $:.unshift(File.expand_path('../../', __FILE__))
2
+ require 'spec_helper'
3
+
4
+ describe Bremen::Mixcloud do
5
+ describe '.search_url' do
6
+ subject{ Bremen::Mixcloud.search_url(params) }
7
+ describe 'only keyword' do
8
+ let(:params){ {keyword: 'searchword'} }
9
+ it 'generate' do
10
+ subject.must_equal 'http://api.mixcloud.com/search/?q=searchword&limit=20&type=cloudcast'
11
+ end
12
+ end
13
+
14
+ describe 'full params' do
15
+ let(:params){ {keyword: 'searchword', limit: 1} }
16
+ it 'generate' do
17
+ subject.must_equal 'http://api.mixcloud.com/search/?q=searchword&limit=1&type=cloudcast'
18
+ end
19
+ end
20
+ end
21
+
22
+ describe '.convert_from_response' do
23
+ subject{ Bremen::Mixcloud.send(:convert_from_response, response) }
24
+ let(:response){ fixture('mixcloud.json') }
25
+ it 'convert successfully' do
26
+ subject.first.title.must_equal 'Title'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ $:.unshift(File.expand_path('../../', __FILE__))
2
+ require 'spec_helper'
3
+
4
+ describe Bremen::Nicovideo do
5
+ describe '.search_url' do
6
+ subject{ Bremen::Nicovideo.search_url(params) }
7
+ describe 'only keyword' do
8
+ let(:params){ {keyword: 'searchword'} }
9
+ it 'generate' do
10
+ subject.must_equal 'http://www.nicovideo.jp/search/searchword?sort=f&order=d&f_range=&l_range=&opt_md='
11
+ end
12
+ end
13
+
14
+ describe 'full params' do
15
+ let(:params){ {keyword: 'searchword', sort: 'n', order: 'a', within: 3, length: 2, downloadable: 1} }
16
+ it 'generate' do
17
+ subject.must_equal 'http://www.nicovideo.jp/search/searchword?sort=n&order=a&f_range=3&l_range=2&opt_md=1'
18
+ end
19
+ end
20
+ end
21
+
22
+ describe '.convert_from_response' do
23
+ subject{ Bremen::Nicovideo.send(:convert_from_response, response) }
24
+ let(:response){ fixture('nicovideo.html') }
25
+ it 'convert successfully' do
26
+ subject.first.title.must_equal 'Title'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ $:.unshift(File.expand_path('../../', __FILE__))
2
+ require 'spec_helper'
3
+
4
+ describe Bremen::Soundcloud do
5
+ describe '.search_url' do
6
+ describe 'not set consumer_key' do
7
+ it 'raise error' do
8
+ lambda{ Bremen::Soundcloud.search_url }.must_raise RuntimeError
9
+ end
10
+ end
11
+ describe 'set consumer_key' do
12
+ before{ Bremen::Soundcloud.consumer_key = 'CK' }
13
+ subject{ Bremen::Soundcloud.search_url(params) }
14
+ describe 'only keyword' do
15
+ let(:params){ {keyword: 'searchword'} }
16
+ it 'generate' do
17
+ subject.must_equal 'http://api.soundcloud.com/tracks.json?q=searchword&order=created_at&limit=50&filter=&consumer_key=CK'
18
+ end
19
+ end
20
+
21
+ describe 'full params' do
22
+ let(:params){ {keyword: 'searchword', order: 'hotness', limit: 1, filter: 'public'} }
23
+ it 'generate' do
24
+ subject.must_equal 'http://api.soundcloud.com/tracks.json?q=searchword&order=hotness&limit=1&filter=public&consumer_key=CK'
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '.convert_from_response' do
31
+ subject{ Bremen::Soundcloud.send(:convert_from_response, response) }
32
+ let(:response){ fixture('soundcloud.json') }
33
+ it 'convert successfully' do
34
+ subject.first.title.must_equal 'Title'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ $:.unshift(File.expand_path('../../', __FILE__))
2
+ require 'spec_helper'
3
+
4
+ describe Bremen::Youtube do
5
+ describe '.search_url' do
6
+ subject{ Bremen::Youtube.search_url(params) }
7
+ describe 'only keyword' do
8
+ let(:params){ {keyword: 'searchword'} }
9
+ it 'generate' do
10
+ subject.must_equal 'http://gdata.youtube.com/feeds/api/videos/-/Music//?vq=searchword&orderby=published&max-results=25&alt=json'
11
+ end
12
+ end
13
+
14
+ describe 'full params' do
15
+ let(:params){ {keyword: 'searchword', order: 'relevance', limit: 1, category: 'Entertainment', tag: 'game'} }
16
+ it 'generate' do
17
+ subject.must_equal 'http://gdata.youtube.com/feeds/api/videos/-/Entertainment/game/?vq=searchword&orderby=relevance&max-results=1&alt=json'
18
+ end
19
+ end
20
+ end
21
+
22
+ describe '.convert_from_response' do
23
+ subject{ Bremen::Youtube.send(:convert_from_response, response) }
24
+ let(:response){ fixture('youtube.json') }
25
+ it 'convert successfully' do
26
+ subject.first.title.must_equal 'Title'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,50 @@
1
+ {
2
+ "paging": {
3
+ "next": "http://api.mixcloud.com/search/?q=searchword&type=cloudcast&limit=1&offset=1"
4
+ },
5
+ "data": [
6
+ {
7
+ "listener_count": 111,
8
+ "name": "Title",
9
+ "tags": [
10
+ {
11
+ "url": "http://www.mixcloud.com/tag/tag1/",
12
+ "name": "Inna",
13
+ "key": "/tag/tag1/"
14
+ }
15
+ ],
16
+ "url": "http://www.mixcloud.com/author/title/",
17
+ "pictures": {
18
+ "medium": "http://images-mix.netdna-ssl.com/w/100/h/100/q/85/upload/images/extaudio/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
19
+ "extra_large": "http://images-mix.netdna-ssl.com/w/600/h/600/q/85/upload/images/extaudio/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
20
+ "large": "http://images-mix.netdna-ssl.com/w/300/h/300/q/85/upload/images/extaudio/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
21
+ "medium_mobile": "http://images-mix.netdna-ssl.com/w/80/h/80/q/75/upload/images/extaudio/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
22
+ "small": "http://images-mix.netdna-ssl.com/w/25/h/25/q/85/upload/images/extaudio/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
23
+ "thumbnail": "http://images-mix.netdna-ssl.com/w/50/h/50/q/85/upload/images/extaudio/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png"
24
+ },
25
+ "updated_time": "2012-01-01T00:00:00Z",
26
+ "play_count": 1111,
27
+ "comment_count": 1,
28
+ "percentage_music": 100,
29
+ "user": {
30
+ "url": "http://www.mixcloud.com/author/",
31
+ "username": "author",
32
+ "name": "Author",
33
+ "key": "/author/",
34
+ "pictures": {
35
+ "medium": "http://images-mix.netdna-ssl.com/w/100/h/100/q/85/upload/images/profile/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
36
+ "extra_large": "http://images-mix.netdna-ssl.com/w/600/h/600/q/85/upload/images/profile/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
37
+ "large": "http://images-mix.netdna-ssl.com/w/300/h/300/q/85/upload/images/profile/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
38
+ "medium_mobile": "http://images-mix.netdna-ssl.com/w/80/h/80/q/75/upload/images/profile/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
39
+ "small": "http://images-mix.netdna-ssl.com/w/25/h/25/q/85/upload/images/profile/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.png",
40
+ "thumbnail": "http://images-mix.netdna-ssl.com/w/50/h/50/q/85/upload/images/profile/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx.png"
41
+ }
42
+ },
43
+ "key": "/author/title/",
44
+ "created_time": "2011-06-12T10:40:19Z",
45
+ "audio_length": 1111,
46
+ "slug": "title",
47
+ "favorite_count": 11
48
+ }
49
+ ]
50
+ }
@@ -0,0 +1,44 @@
1
+ <html>
2
+ <body>
3
+ <div class="thumb_col_1">
4
+ <!---->
5
+ <table width="624" cellpadding="4" cellspacing="0" summary="sm11111111">
6
+ <tr valign="top">
7
+ <td><div id="item1" style="display:none;" onMouseover="showOBJ('thumb_uad_msg_sm11111111')" onMouseout="hideOBJ('thumb_uad_msg_sm11111111')">
8
+ <div id="thumb_uad_msg_sm11111111" style="display:none; position:absolute;">
9
+ <p id="item1_uad_comment" class="uad_comment"><span style="color:#666;">-</span></p>
10
+ </div>
11
+ </div>
12
+ <div id="item1_thumb" class="uad_thumbfrm">
13
+ <table cellspacing="0" cellpadding="0">
14
+ <tr>
15
+ <td onMouseover="showOBJ('thumb_uad_msg_sm11111111')" onMouseout="hideOBJ('thumb_uad_msg_sm11111111')">
16
+ <p><a href="watch/sm11111111"><img src="http://tn-skr4.smilevideo.jp/smile?i=11111111" alt="" class="img_std96"></a></p>
17
+ <p class="vinfo_length"><span>1:01</span></p>
18
+ </td>
19
+ <td class="font10" align="right"><div style="width:92px; overflow:hidden; padding-left:4px;"><nobr>Views: <strong class="vinfo_view">111</strong><br></nobr>
20
+ <nobr>Comments: <strong class="vinfo_res">1</strong><br></nobr>
21
+ <nobr>My Lists: <a href="mylistcomment/video/sm11111111" style="color:#393F3F;"><strong class="vinfo_mylist">9</strong></a><br></nobr>
22
+ <nobr>Ads: <a href="http://uad.nicovideo.jp/ads/?vid=sm11111111" style="color:#393F3F;"><strong id="item1_uad_point_number" class="vinfo_uadp">0</strong></a><br></nobr>
23
+ </div></td>
24
+ </tr>
25
+ </table>
26
+ </div>
27
+ </td>
28
+ <td style="background:url('http://res.nimg.jp/img/common/thumb/split_line.png') no-repeat bottom left; padding-bottom:6px;">
29
+ <div style="width:412px; overflow:hidden;">
30
+ <p class="font12 thumb_num">
31
+
32
+
33
+ Uploaded on: <strong>Nov 11, 2012, 00:00</strong>
34
+ </p>
35
+ <p class="font16" style="margin:2px 0;"><nobr><a href="watch/sm11111111" class="watch" title="Title">Title</a></nobr></p>
36
+ <p class="vinfo_description" title="This is a description.">This is a description.</p>
37
+ </div>
38
+ </td>
39
+ </tr>
40
+ </table>
41
+ <!---->
42
+ </div></div>
43
+ </body>
44
+ </html>
@@ -0,0 +1,55 @@
1
+ [
2
+ {
3
+ "artwork_url": "http://i1.sndcdn.com/artworks-000011111111-1cfbic-large.jpg?5c687d0",
4
+ "attachments_uri": "http://api.soundcloud.com/tracks/11111111/attachments",
5
+ "bpm": null,
6
+ "comment_count": 0,
7
+ "commentable": true,
8
+ "created_at": "2012/01/01 00:08:00 +0000",
9
+ "description": "",
10
+ "download_count": 0,
11
+ "downloadable": false,
12
+ "duration": 111111,
13
+ "embeddable_by": "all",
14
+ "favoritings_count": 0,
15
+ "genre": "Garage",
16
+ "id": 11111111,
17
+ "isrc": "",
18
+ "key_signature": "",
19
+ "kind": "track",
20
+ "label_id": null,
21
+ "label_name": "",
22
+ "license": "all-rights-reserved",
23
+ "original_content_size": 1111111,
24
+ "original_format": "mp3",
25
+ "permalink": "permalink",
26
+ "permalink_url": "http://soundcloud.com/author/permalink",
27
+ "playback_count": 4,
28
+ "purchase_title": null,
29
+ "purchase_url": null,
30
+ "release": "",
31
+ "release_day": null,
32
+ "release_month": null,
33
+ "release_year": null,
34
+ "sharing": "public",
35
+ "state": "finished",
36
+ "stream_url": "http://api.soundcloud.com/tracks/11111111/stream",
37
+ "streamable": true,
38
+ "tag_list": "tag1 tag2 tag3",
39
+ "title": "Title",
40
+ "track_type": "",
41
+ "uri": "http://api.soundcloud.com/tracks/11111111",
42
+ "user": {
43
+ "avatar_url": "http://i1.sndcdn.com/avatars-000011111111-zzjvpd-large.jpg?5c687d0",
44
+ "id": 11111111,
45
+ "kind": "user",
46
+ "permalink": "author",
47
+ "permalink_url": "http://soundcloud.com/author",
48
+ "uri": "http://api.soundcloud.com/users/11111111",
49
+ "username": "Author"
50
+ },
51
+ "user_id": 11111111,
52
+ "video_url": null,
53
+ "waveform_url": "http://w1.sndcdn.com/XXXXXXXXXXXX_m.png"
54
+ }
55
+ ]
@@ -0,0 +1,241 @@
1
+ {
2
+ "encoding": "UTF-8",
3
+ "feed": {
4
+ "author": [
5
+ {
6
+ "name": {
7
+ "$t": "YouTube"
8
+ },
9
+ "uri": {
10
+ "$t": "http://www.youtube.com/"
11
+ }
12
+ }
13
+ ],
14
+ "category": [
15
+ {
16
+ "scheme": "http://schemas.google.com/g/2005#kind",
17
+ "term": "http://gdata.youtube.com/schemas/2007#video"
18
+ }
19
+ ],
20
+ "entry": [
21
+ {
22
+ "author": [
23
+ {
24
+ "name": {
25
+ "$t": "Author"
26
+ },
27
+ "uri": {
28
+ "$t": "http://gdata.youtube.com/feeds/api/users/Author"
29
+ }
30
+ }
31
+ ],
32
+ "category": [
33
+ {
34
+ "scheme": "http://schemas.google.com/g/2005#kind",
35
+ "term": "http://gdata.youtube.com/schemas/2007#video"
36
+ },
37
+ {
38
+ "label": "Music",
39
+ "scheme": "http://gdata.youtube.com/schemas/2007/categories.cat",
40
+ "term": "Music"
41
+ }
42
+ ],
43
+ "content": {
44
+ "$t": "This is a description.",
45
+ "type": "text"
46
+ },
47
+ "gd$comments": {
48
+ "gd$feedLink": {
49
+ "countHint": 0,
50
+ "href": "http://gdata.youtube.com/feeds/api/videos/XXXXXXXXXXX/comments",
51
+ "rel": "http://gdata.youtube.com/schemas/2007#comments"
52
+ }
53
+ },
54
+ "id": {
55
+ "$t": "http://gdata.youtube.com/feeds/api/videos/XXXXXXXXXXX"
56
+ },
57
+ "link": [
58
+ {
59
+ "href": "http://www.youtube.com/watch?v=XXXXXXXXXXX&feature=youtube_gdata",
60
+ "rel": "alternate",
61
+ "type": "text/html"
62
+ },
63
+ {
64
+ "href": "http://gdata.youtube.com/feeds/api/videos/XXXXXXXXXXX/responses",
65
+ "rel": "http://gdata.youtube.com/schemas/2007#video.responses",
66
+ "type": "application/atom+xml"
67
+ },
68
+ {
69
+ "href": "http://gdata.youtube.com/feeds/api/videos/XXXXXXXXXXX/related",
70
+ "rel": "http://gdata.youtube.com/schemas/2007#video.related",
71
+ "type": "application/atom+xml"
72
+ },
73
+ {
74
+ "href": "http://m.youtube.com/details?v=XXXXXXXXXXX",
75
+ "rel": "http://gdata.youtube.com/schemas/2007#mobile",
76
+ "type": "text/html"
77
+ },
78
+ {
79
+ "href": "http://gdata.youtube.com/feeds/api/videos/XXXXXXXXXXX",
80
+ "rel": "self",
81
+ "type": "application/atom+xml"
82
+ }
83
+ ],
84
+ "media$group": {
85
+ "media$category": [
86
+ {
87
+ "$t": "Music",
88
+ "label": "Music",
89
+ "scheme": "http://gdata.youtube.com/schemas/2007/categories.cat"
90
+ }
91
+ ],
92
+ "media$content": [
93
+ {
94
+ "duration": 308,
95
+ "expression": "full",
96
+ "isDefault": "true",
97
+ "medium": "video",
98
+ "type": "application/x-shockwave-flash",
99
+ "url": "http://www.youtube.com/v/XXXXXXXXXXX?version=3&f=videos&app=youtube_gdata",
100
+ "yt$format": 5
101
+ },
102
+ {
103
+ "duration": 308,
104
+ "expression": "full",
105
+ "medium": "video",
106
+ "type": "video/3gpp",
107
+ "url": "rtsp://v8.cache4.c.youtube.com/CiILENy73wIaGQn8RbFfqUC_OxMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp",
108
+ "yt$format": 1
109
+ },
110
+ {
111
+ "duration": 308,
112
+ "expression": "full",
113
+ "medium": "video",
114
+ "type": "video/3gpp",
115
+ "url": "rtsp://v1.cache7.c.youtube.com/CiILENy73wIaGQn8RbFfqUC_OxMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp",
116
+ "yt$format": 6
117
+ }
118
+ ],
119
+ "media$description": {
120
+ "$t": "This is a description.",
121
+ "type": "plain"
122
+ },
123
+ "media$keywords": {},
124
+ "media$player": [
125
+ {
126
+ "url": "http://www.youtube.com/watch?v=XXXXXXXXXXX&feature=youtube_gdata_player"
127
+ }
128
+ ],
129
+ "media$thumbnail": [
130
+ {
131
+ "height": 360,
132
+ "time": "00:02:34",
133
+ "url": "http://i.ytimg.com/vi/XXXXXXXXXXX/0.jpg",
134
+ "width": 480
135
+ },
136
+ {
137
+ "height": 90,
138
+ "time": "00:01:17",
139
+ "url": "http://i.ytimg.com/vi/XXXXXXXXXXX/1.jpg",
140
+ "width": 120
141
+ },
142
+ {
143
+ "height": 90,
144
+ "time": "00:02:34",
145
+ "url": "http://i.ytimg.com/vi/XXXXXXXXXXX/2.jpg",
146
+ "width": 120
147
+ },
148
+ {
149
+ "height": 90,
150
+ "time": "00:03:51",
151
+ "url": "http://i.ytimg.com/vi/XXXXXXXXXXX/3.jpg",
152
+ "width": 120
153
+ }
154
+ ],
155
+ "media$title": {
156
+ "$t": "Title",
157
+ "type": "plain"
158
+ },
159
+ "yt$duration": {
160
+ "seconds": "308"
161
+ }
162
+ },
163
+ "published": {
164
+ "$t": "2012-01-01T00:50:00.000Z"
165
+ },
166
+ "title": {
167
+ "$t": "Title",
168
+ "type": "text"
169
+ },
170
+ "updated": {
171
+ "$t": "2012-01-01T00:50:00.000Z"
172
+ },
173
+ "yt$hd": {},
174
+ "yt$statistics": {
175
+ "favoriteCount": "0",
176
+ "viewCount": "1"
177
+ }
178
+ }
179
+ ],
180
+ "generator": {
181
+ "$t": "YouTube data API",
182
+ "uri": "http://gdata.youtube.com",
183
+ "version": "2.1"
184
+ },
185
+ "id": {
186
+ "$t": "http://gdata.youtube.com/feeds/api/videos"
187
+ },
188
+ "link": [
189
+ {
190
+ "href": "http://www.youtube.com",
191
+ "rel": "alternate",
192
+ "type": "text/html"
193
+ },
194
+ {
195
+ "href": "http://gdata.youtube.com/feeds/api/videos",
196
+ "rel": "http://schemas.google.com/g/2005#feed",
197
+ "type": "application/atom+xml"
198
+ },
199
+ {
200
+ "href": "http://gdata.youtube.com/feeds/api/videos/batch",
201
+ "rel": "http://schemas.google.com/g/2005#batch",
202
+ "type": "application/atom+xml"
203
+ },
204
+ {
205
+ "href": "http://gdata.youtube.com/feeds/api/videos/-/%7Bhttp%3A%2F%2Fgdata.youtube.com%2Fschemas%2F2007%2Fcategories.cat%7DMusic?alt=json&start-index=1&max-results=1&vq=searchword&orderby=published",
206
+ "rel": "self",
207
+ "type": "application/atom+xml"
208
+ },
209
+ {
210
+ "href": "http://gdata.youtube.com/feeds/api/videos/-/%7Bhttp%3A%2F%2Fgdata.youtube.com%2Fschemas%2F2007%2Fcategories.cat%7DMusic?alt=json&start-index=2&max-results=1&vq=searchword&orderby=published",
211
+ "rel": "next",
212
+ "type": "application/atom+xml"
213
+ }
214
+ ],
215
+ "logo": {
216
+ "$t": "http://www.youtube.com/img/pic_youtubelogo_123x63.gif"
217
+ },
218
+ "openSearch$itemsPerPage": {
219
+ "$t": 1
220
+ },
221
+ "openSearch$startIndex": {
222
+ "$t": 1
223
+ },
224
+ "openSearch$totalResults": {
225
+ "$t": 1111
226
+ },
227
+ "title": {
228
+ "$t": "Videos matching: searchword",
229
+ "type": "text"
230
+ },
231
+ "updated": {
232
+ "$t": "2012-01-01T00:50:00.000Z"
233
+ },
234
+ "xmlns": "http://www.w3.org/2005/Atom",
235
+ "xmlns$gd": "http://schemas.google.com/g/2005",
236
+ "xmlns$media": "http://search.yahoo.com/mrss/",
237
+ "xmlns$openSearch": "http://a9.com/-/spec/opensearchrss/1.0/",
238
+ "xmlns$yt": "http://gdata.youtube.com/schemas/2007"
239
+ },
240
+ "version": "1.0"
241
+ }
@@ -0,0 +1,6 @@
1
+ require 'minitest/autorun'
2
+ require 'bremen'
3
+
4
+ def fixture path
5
+ File.read("#{File.dirname(__FILE__)}/fixtures/#{path}")
6
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bremen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - itzki
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: guard-minitest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rb-fsevent
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: integrated searcher of audio track on music sites
47
+ email:
48
+ - itzki.h@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - Guardfile
56
+ - LICENSE.txt
57
+ - README.md
58
+ - Rakefile
59
+ - bremen.gemspec
60
+ - lib/bremen.rb
61
+ - lib/bremen/base.rb
62
+ - lib/bremen/mixcloud.rb
63
+ - lib/bremen/nicovideo.rb
64
+ - lib/bremen/request.rb
65
+ - lib/bremen/soundcloud.rb
66
+ - lib/bremen/track.rb
67
+ - lib/bremen/version.rb
68
+ - lib/bremen/youtube.rb
69
+ - spec/bremen/mixcloud_spec.rb
70
+ - spec/bremen/nicovideo_spec.rb
71
+ - spec/bremen/soundcloud_spec.rb
72
+ - spec/bremen/youtube_spec.rb
73
+ - spec/fixtures/mixcloud.json
74
+ - spec/fixtures/nicovideo.html
75
+ - spec/fixtures/soundcloud.json
76
+ - spec/fixtures/youtube.json
77
+ - spec/spec_helper.rb
78
+ homepage: https://github.com/itzki/bremen
79
+ licenses: []
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 1.8.23
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: integrated searcher of audio track on music sites
102
+ test_files:
103
+ - spec/bremen/mixcloud_spec.rb
104
+ - spec/bremen/nicovideo_spec.rb
105
+ - spec/bremen/soundcloud_spec.rb
106
+ - spec/bremen/youtube_spec.rb
107
+ - spec/fixtures/mixcloud.json
108
+ - spec/fixtures/nicovideo.html
109
+ - spec/fixtures/soundcloud.json
110
+ - spec/fixtures/youtube.json
111
+ - spec/spec_helper.rb