hype 42.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +17 -0
- data/bin/hype.rb +165 -0
- data/gemspec.rb +28 -0
- metadata +49 -0
data/README
ADDED
data/bin/hype.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems' rescue nil
|
4
|
+
require 'cgi'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'thread'
|
7
|
+
require 'digest/md5'
|
8
|
+
#require 'sqlite'
|
9
|
+
#require 'arrayfields'
|
10
|
+
|
11
|
+
#
|
12
|
+
# opts/config
|
13
|
+
#
|
14
|
+
uris_only = ARGV.delete('--uris') || ARGV.delete('-u')
|
15
|
+
noop = ARGV.delete('--noop') || ARGV.delete('-n')
|
16
|
+
pcast_only = ARGV.delete('--pcast') || ARGV.delete('-p')
|
17
|
+
|
18
|
+
prefix = File.join(File.expand_path('~'), '.hype')
|
19
|
+
|
20
|
+
cache = File.join prefix, 'cache'
|
21
|
+
db = File.join prefix, 'db'
|
22
|
+
|
23
|
+
uris = []
|
24
|
+
#
|
25
|
+
# utils
|
26
|
+
#
|
27
|
+
def homogename path
|
28
|
+
|
29
|
+
new = "#{ path }"
|
30
|
+
new.gsub! %r{[^a-zA-Z0-9_/\.-]}, '_'
|
31
|
+
new.gsub! %r{__+}, '_'
|
32
|
+
new.gsub! %r{_+-_+}, '-'
|
33
|
+
new.gsub! %r{--+}, '-'
|
34
|
+
new.strip
|
35
|
+
|
36
|
+
end
|
37
|
+
def sync
|
38
|
+
|
39
|
+
(@mutex||=Mutex.new).synchronize{ yield }
|
40
|
+
|
41
|
+
end
|
42
|
+
#
|
43
|
+
# setup
|
44
|
+
#
|
45
|
+
FileUtils.mkdir_p prefix
|
46
|
+
FileUtils.mkdir_p cache
|
47
|
+
sync{ system "sqlite #{ db } 'create table mp3s( pathname, md5, primary key(md5) )' >/dev/null 2>&1" }
|
48
|
+
|
49
|
+
q = SizedQueue.new 10
|
50
|
+
reaper = Thread.new {
|
51
|
+
loop{
|
52
|
+
t = q.pop or Thread.current.exit
|
53
|
+
#puts t.value
|
54
|
+
t.value
|
55
|
+
}
|
56
|
+
}
|
57
|
+
#
|
58
|
+
# crawl
|
59
|
+
#
|
60
|
+
user_agent = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.4) Gecko/20060508 Firefox/1.5.0.4'
|
61
|
+
pcast_xml_uri = 'http://hype.non-standard.net/playlist/time/today/pcast/1/feed.pcast'
|
62
|
+
|
63
|
+
pcast_xml = `curl --location --silent --user-agent '#{ user_agent }' '#{ pcast_xml_uri }'`
|
64
|
+
if pcast_only
|
65
|
+
puts pcast_xml
|
66
|
+
exit
|
67
|
+
end
|
68
|
+
|
69
|
+
m = %r/href\s*=\s*["']?([^"'\s][^\s]+[^"'\s])["']?/.match pcast_xml
|
70
|
+
abort 'no feed!' unless m
|
71
|
+
feed_xml_uri = String m[1]
|
72
|
+
feed_xml = `curl --location --silent --user-agent '#{ user_agent }' '#{ feed_xml_uri }'`
|
73
|
+
|
74
|
+
#
|
75
|
+
# <enclosure
|
76
|
+
# url="http://hype.non-standard.net/serve/r/300/102400/02AndIWasABoyFromSchool-9688.mp3"
|
77
|
+
# length="3917090" type="audio/mpeg"/>
|
78
|
+
#
|
79
|
+
if uris.empty?
|
80
|
+
feed_xml.each do |line|
|
81
|
+
if line =~ %r/enclosure/
|
82
|
+
m = %r/length\s*=\s*["']?([^"'\s][^\s]+[^"'\s])["']?/.match line
|
83
|
+
next unless m
|
84
|
+
length = Integer m[1]
|
85
|
+
|
86
|
+
m = %r/url\s*=\s*["']?([^"'\s][^\s]+[^"'\s])["']?/.match line
|
87
|
+
next unless m
|
88
|
+
uri = String m[1]
|
89
|
+
|
90
|
+
uris << [uri, length]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
if uris_only
|
96
|
+
puts uris.map{|pair| pair.first}
|
97
|
+
exit
|
98
|
+
end
|
99
|
+
|
100
|
+
Dir.chdir(cache) do
|
101
|
+
uris.sort_by{ rand }.each do |src, length|
|
102
|
+
basename = CGI.unescape(File.basename(src))
|
103
|
+
dst = homogename basename
|
104
|
+
dst << '.mp3' unless dst[%r/\.mp3$/]
|
105
|
+
|
106
|
+
# make sure output name is unique
|
107
|
+
i = 0
|
108
|
+
while test ?e, dst
|
109
|
+
print "#{ dst } -->> "
|
110
|
+
newdst = dst.gsub %r/\.mp3$/, "_#{ i += 1 }.mp3"
|
111
|
+
abort "#{ dst } == #{ newdst }" if dst == newdst
|
112
|
+
dst = newdst
|
113
|
+
puts dst
|
114
|
+
end
|
115
|
+
|
116
|
+
# grab stat - this should always be nil!
|
117
|
+
stat = File.stat(dst) rescue nil
|
118
|
+
abort "clobbering <#{ dst }>" if stat
|
119
|
+
|
120
|
+
unless stat and stat.size == length
|
121
|
+
q.push Thread.new{
|
122
|
+
t = Thread.current
|
123
|
+
t.abort_on_exception = true
|
124
|
+
cmd = "curl --location --silent --user-agent '#{ user_agent }' '#{ src }' > '#{ dst }'"
|
125
|
+
|
126
|
+
ret =
|
127
|
+
unless noop
|
128
|
+
puts cmd
|
129
|
+
begin
|
130
|
+
system cmd or raise
|
131
|
+
rescue
|
132
|
+
FileUtils.rm_f dst # kill partial downloads instantly
|
133
|
+
end
|
134
|
+
else
|
135
|
+
cmd
|
136
|
+
end
|
137
|
+
|
138
|
+
#system "stat #{ dst }"
|
139
|
+
File.stat(dst) rescue next
|
140
|
+
|
141
|
+
md5 = Digest::MD5.hexdigest(dst)
|
142
|
+
|
143
|
+
# try to update db, iff we fail it means we'd already downloaded this
|
144
|
+
# file
|
145
|
+
success = sync{ system %Q(sqlite #{ db } "insert into mp3s values('#{ dst }', '#{ md5 }')" >/dev/null 2>&1) }
|
146
|
+
unless success
|
147
|
+
pair = sync{ ` sqlite #{ db } " select * from mp3s where md5 = '#{ md5 }' " `.to_s.chomp }
|
148
|
+
#a,b= ( pair.split(%r/\|/,2) rescue [] )
|
149
|
+
a,b= pair.split(%r/\|/,2)
|
150
|
+
warn "rm -f '#{ dst }' (#{ a },#{ b })"
|
151
|
+
FileUtils.rm_f dst ## unless stat # rm unless it was pre-existing
|
152
|
+
end
|
153
|
+
|
154
|
+
ret
|
155
|
+
}
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
q.push nil
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# wait for reaper
|
164
|
+
#
|
165
|
+
reaper.join
|
data/gemspec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
Gem::Specification::new do |spec|
|
7
|
+
$VERBOSE = nil
|
8
|
+
spec.name = lib
|
9
|
+
spec.version = version
|
10
|
+
spec.platform = Gem::Platform::RUBY
|
11
|
+
spec.summary = lib
|
12
|
+
|
13
|
+
spec.files = Dir::glob "**/**"
|
14
|
+
spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
|
15
|
+
|
16
|
+
spec.require_path = "lib"
|
17
|
+
spec.autorequire = lib
|
18
|
+
|
19
|
+
spec.has_rdoc = File::exist? "doc"
|
20
|
+
spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
|
21
|
+
#spec.add_dependency 'lib', '>= version'
|
22
|
+
|
23
|
+
spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
|
24
|
+
|
25
|
+
spec.author = "Ara T. Howard"
|
26
|
+
spec.email = "ara.t.howard@gmail.com"
|
27
|
+
spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: hype
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 42.0.0
|
7
|
+
date: 2007-07-11 00:00:00 -06:00
|
8
|
+
summary: hype
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: ara.t.howard@gmail.com
|
12
|
+
homepage: http://codeforpeople.com/lib/ruby/hype/
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: hype
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Ara T. Howard
|
31
|
+
files:
|
32
|
+
- bin
|
33
|
+
- bin/hype.rb
|
34
|
+
- gemspec.rb
|
35
|
+
- README
|
36
|
+
test_files: []
|
37
|
+
|
38
|
+
rdoc_options: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
executables:
|
43
|
+
- hype.rb
|
44
|
+
extensions: []
|
45
|
+
|
46
|
+
requirements: []
|
47
|
+
|
48
|
+
dependencies: []
|
49
|
+
|