music_videos 0.0.12

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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Njc0M2YwNmMwOTRhMzZkMjk4YjFlNDVkMTI5Y2U1YjNiNzY1YTc3Yg==
5
+ data.tar.gz: !binary |-
6
+ M2FjMDZhNmJjZDIyMDEzZjEyNGFlZWEyNTc5ZGUzNzE2ZjAyYzFjOQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZmU0NGVlZjVhODExODQ3MTIwODA2ZTVlY2UyYjdhMmNiNmY3MjEwZGY3NDUx
10
+ MWZjZjljNWNiMGJiMGUyNWI2ZTA3Mzk3ZTE1N2Q2OTczMDJhOGViZDA5NzMw
11
+ NGQyMzg4MGRhMTcxNjhhODAzNTA3MDQ4ODAyZTk0NzkwMWFmMzU=
12
+ data.tar.gz: !binary |-
13
+ YjRkNzc0OTg1OWQ2MTlmZDljYmU3MmE5YTA1MWZkOGI0MWQxNWZkOTQ2YjAx
14
+ ZmU2NjcyMTQzYzhjOWEyMzVjNGNlYTZkYmZhMjg5ZjQ1YWI1MDE2OTNhNzA0
15
+ YTU4Yzg1Yjc4NDIyY2Q5MzRlMzEzOTYxMmRkYjBmZWQzNzI3MjA=
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ music_videos-*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in music_videos.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 thenotic
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,39 @@
1
+ # MusicVideos
2
+
3
+ To get an artist's music videos you need a lastfm api key as well as a youtube api key.
4
+
5
+ ```ruby
6
+ v = MusicVideos::Find.new(LASTFM_API_KEY, 30711e29ad09c493dad2831eb0bbd08",YOUTUBE_API_KEY)
7
+ music_videos = v.find_artist_music_videos("gucci mane")
8
+
9
+ v.first
10
+ ##<Object:0x007fe4ed1d2638 @artist="chief keef", @title="early morning getting it", @youtube_url="Mt07J2k8myM">
11
+ ```
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'music_videos'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install music_videos
28
+
29
+ ## Usage
30
+
31
+ TODO: Write usage instructions here
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( https://github.com/[my-github-username]/music_videos/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,237 @@
1
+ require 'open-uri'
2
+ require 'json'
3
+ require 'nokogiri'
4
+ require 'typhoeus'
5
+ require 'rmagick'
6
+
7
+ module MusicVideos
8
+ class Find
9
+
10
+ def initialize(lastfm_api_key, youtube_api_key)
11
+ @lastfm_api_key = lastfm_api_key
12
+ @youtube_api_key = youtube_api_key
13
+ end
14
+
15
+ def get_artist_songs(lastfm_name)
16
+ tracks = []
17
+ for i in (0..5)
18
+ url = "http://ws.audioscrobbler.com/2.0/?api_key=#{@lastfm_api_key}&format=json&artist=#{lastfm_name}&method=artist.getTopTracks&limit=100&page=#{i}"
19
+ tracks << JSON.parse(open(url).read)['toptracks']['track'].map{|x| x['name']} rescue next
20
+ end
21
+ return tracks
22
+ end
23
+
24
+
25
+ def artist_search(artist_name)
26
+ url = "http://ws.audioscrobbler.com/2.0/?api_key=#{@lastfm_api_key}&format=json&artist=#{URI.encode(artist_name)}&method=artist.search"
27
+ lastfm_name = JSON.parse(open(url).read)['results']['artistmatches']['artist'][0]['url'].gsub("http://www.last.fm/music/","")
28
+ return lastfm_name
29
+ end
30
+
31
+ def get_clean_tracks(tracks)
32
+ tracks_clean = tracks.flatten.uniq.reject{|x| x.to_s.downcase.gsub(/\([^()]*\)/,"").scan(/feat|ft|\)|prod| \- |\||\]|dir/).count > 0 rescue next}.map{|x| x.downcase.gsub("in'","ing").gsub(/\([^()]*\)/,"")}.uniq
33
+ tt = []
34
+ tracks_clean.compact.each do |x|
35
+ if x[0].match(/[0-9]/)
36
+ tt << x.gsub(/^[0-9]*/,'')[1..-1].join(" ").gsub(".","").strip rescue next
37
+ else
38
+ tt << x
39
+ end
40
+ end
41
+ return tt
42
+ end
43
+
44
+ def get_youtube_links(artist,tt)
45
+ l = artist
46
+ i = 1
47
+ yy = []
48
+ checkyy = []
49
+ hydra = Typhoeus::Hydra.new
50
+ tt.compact.each do |x|
51
+ i = i+1;puts i
52
+ artist = l
53
+ title = x
54
+ artist.gsub!('&',' and ')
55
+ title.gsub!('&',' and ')
56
+ search ="#{URI.encode(artist.gsub(/\(.*?\)/, ''))}%20#{URI.encode(title.gsub(/\(.*?\)/, ''))}"
57
+ url = "https://www.googleapis.com/youtube/v3/search?q=#{search}&key=#{@youtube_api_key}&part=snippet&type=video" #api key as 2nd gmail
58
+ request = Typhoeus::Request.new(url, followlocation: false)
59
+ request.on_complete do |response|
60
+ page = JSON.parse(Nokogiri::HTML(response.body)) rescue next
61
+ first_link = page['items'][0]['id']['videoId'] rescue next
62
+ y_title = page['items'][0]['snippet']['title'] rescue next
63
+ x_title = "#{x} #{l}"
64
+ confidence = x_title.downcase ^ y_title.downcase
65
+ confidence2 = ccc(artist,title,y_title)
66
+ if confidence > 0.6 || (confidence2 > 0.65)
67
+ unless y_title.downcase.match(/lyric|review|cover/)
68
+ yy << [x, first_link, y_title, title, confidence]
69
+ end
70
+ end
71
+ end
72
+ hydra.queue(request)
73
+ end
74
+ hydra.run
75
+
76
+ return yy
77
+
78
+ end
79
+
80
+
81
+ def ccc(artist,title,y_title)
82
+ total_title = "#{artist.gsub(/\(.*?\)/, '').downcase} #{title.downcase}".split(' ')
83
+ y_title_real = y_title.downcase.split(' ')
84
+ score = (1.to_f - (total_title - y_title_real).count.to_f / total_title.count.to_f)
85
+ return score
86
+ end
87
+
88
+
89
+ def get_previews(yy)
90
+ yy = yy.uniq{|x| x[1]}
91
+ k = []
92
+ hydra = Typhoeus::Hydra.new(max_concurrency: 20)
93
+ yy.each do |x|
94
+ url = "http://www.genyoutube.com/preview.php?id=#{x[1]}"
95
+ request = Typhoeus::Request.new(url, followlocation: false, )
96
+ request.on_complete do |response|
97
+ page = Nokogiri::HTML(response.body) rescue next
98
+ image_url = page.css('img').select{|x| x.attr('src').to_s.include?('/M1')}[0].attr('src').to_s rescue page.css('img')[0].attr('src').to_s rescue next
99
+ k << [x[0], x[1].gsub('watch.php?v=',''), image_url]
100
+ end
101
+ hydra.queue(request)
102
+ end
103
+ hydra.run
104
+
105
+ return k
106
+ end
107
+
108
+ def vid3(image_url)
109
+
110
+ image = Magick::ImageList.new
111
+ urlimage = open(image_url) # Image Remote URL
112
+ image.from_blob(urlimage.read)
113
+
114
+ width = image.columns/5
115
+ height = image.rows/5
116
+ images = []
117
+ 0.upto(5-1) do |x|
118
+ 0.upto(5-1) do |y|
119
+ images << image.crop( Magick::NorthWestGravity, x*width, y*height, width, height, true)
120
+ end
121
+ end
122
+
123
+ diff = images[10].difference(images[11])
124
+
125
+ return diff[1]
126
+
127
+ end
128
+
129
+
130
+ def get_videos(artist, k)
131
+ videos = []
132
+ i = 0
133
+ k.each do |x|
134
+ i = i+1;puts i
135
+ size = vid3(x[2]).to_f
136
+ if size > 0.01
137
+ videos << [x[0], size, x[1]]
138
+ end
139
+ end
140
+ video_output = []; i = 0
141
+ videos.each do |x|
142
+ bb = Object.new
143
+ bb.class.module_eval { attr_accessor :artist, :title, :youtube_url}
144
+ bb.artist = artist
145
+ bb.title = x.flatten[0]
146
+ bb.youtube_url = x.flatten[2]
147
+ video_output << bb
148
+ end
149
+ return video_output
150
+ end
151
+
152
+
153
+
154
+
155
+ def find_artist_music_videos(artist)
156
+ lastfm_name = artist_search(artist)
157
+ tracks = get_artist_songs(lastfm_name)
158
+ clean_tracks = get_clean_tracks(tracks)
159
+ youtube_links = get_youtube_links(artist, clean_tracks)
160
+ previews = get_previews(youtube_links)
161
+ videos = get_videos(artist, previews)
162
+
163
+ return videos
164
+ end
165
+
166
+
167
+ end
168
+
169
+
170
+ end
171
+
172
+ class String
173
+
174
+ def clean_name
175
+ return self.gsub(/\(.*?\)/, '').strip
176
+ end
177
+
178
+
179
+ # Jaro-Winkler distance
180
+ # @param [String] other string
181
+ # @return [Float] distance, normalized between 0.0 (no match) and 1.0 (perfect match)
182
+ def ^(other)
183
+ return 1.0 if self == other
184
+ return 0.0 if self.empty? or other.empty?
185
+
186
+ s1 = self.codepoints.to_a
187
+ s2 = other.codepoints.to_a
188
+ s1, s2 = s2, s1 if s1.size > s2.size
189
+ s1s, s2s = s1.size, s2.size
190
+ m, t = 0.0, 0
191
+ max_dist = s2s/2 - 1
192
+
193
+ m1 = Array.new(s1s, -1)
194
+ m2 = Array.new(s2s, false)
195
+
196
+ # find m
197
+ s1.each_with_index do |a, ia|
198
+ lower = ia > max_dist ? ia-max_dist : 0
199
+ upper = ia+max_dist < s2s ? ia+max_dist : s2s
200
+ s2[lower..upper].each_with_index do |b, ib|
201
+ ib += lower
202
+ if a == b and !m2[ib]
203
+ m, m1[ia], m2[ib] = m+1, ib, true
204
+ break
205
+ end
206
+ end
207
+ end
208
+
209
+ return 0.0 if m.zero?
210
+
211
+ m1.reduce do |a, b|
212
+ # if either a or b are nil, that means there was no match
213
+ # if a > b, that means the previous value is greater than the current
214
+ # which means it went down
215
+ if a > -1 and b > -1 and a > b
216
+ t += (a-b > 1 ? 1 : 2)
217
+ end
218
+ b
219
+ end
220
+
221
+ dj = (m/s1s + m/s2s + (m - t/2)/m) / 3
222
+
223
+ # winkler adjustment
224
+ l = 0
225
+ for i in 0..3
226
+ if s1[i] != s2[i]
227
+ l = i
228
+ break
229
+ end
230
+ end
231
+
232
+ # standard weight (p) for winkler == 0.1
233
+ dj + l*0.1*(1-dj)
234
+ end
235
+ end
236
+
237
+
@@ -0,0 +1,3 @@
1
+ module MusicVideos
2
+ VERSION = "0.0.1"
3
+ end
@@ -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
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "music_videos"
7
+ spec.version = '0.0.12'
8
+ spec.authors = ["thenotic"]
9
+ spec.email = ["liban.aliyusuf@gmail.com"]
10
+ spec.summary = "Finds Artist Music Videos"
11
+ spec.description = "Yes"
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_dependency "typhoeus"
23
+ spec.add_dependency "rmagick"
24
+ spec.add_development_dependency "rspec", "~> 3.2"
25
+
26
+
27
+
28
+
29
+ end
@@ -0,0 +1,5 @@
1
+ require 'music_videos'
2
+
3
+
4
+
5
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: music_videos
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.12
5
+ platform: ruby
6
+ authors:
7
+ - thenotic
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: typhoeus
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rmagick
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '3.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '3.2'
83
+ description: 'Yes'
84
+ email:
85
+ - liban.aliyusuf@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .DS_Store
91
+ - .gitignore
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - lib/music_videos.rb
97
+ - lib/music_videos/version.rb
98
+ - music_videos-0.0.0.gem
99
+ - music_videos-0.0.1.gem
100
+ - music_videos-0.0.2.gem
101
+ - music_videos-0.0.3.gem
102
+ - music_videos-0.0.5.gem
103
+ - music_videos-0.0.6.gem
104
+ - music_videos-0.0.7.gem
105
+ - music_videos-0.0.8.gem
106
+ - music_videos.gemspec
107
+ - spec/music_videos.spec
108
+ homepage: ''
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.2.2
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Finds Artist Music Videos
132
+ test_files:
133
+ - spec/music_videos.spec