thingfish 0.5.0.pre20161103181816 → 0.5.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +8739 -0
- data/Gemfile +2 -0
- data/History.rdoc +4 -2
- data/Manifest.txt +0 -2
- data/README.rdoc +12 -8
- data/Rakefile +4 -5
- data/etc/mongrel2-config.rb +57 -0
- data/lib/thingfish.rb +1 -12
- data/lib/thingfish/handler.rb +47 -20
- data/lib/thingfish/processor/sha256.rb +51 -0
- data/spec/thingfish/handler_spec.rb +30 -13
- data/spec/thingfish/processor/{mp3_spec.rb → sha256_spec.rb} +10 -11
- metadata +11 -22
- metadata.gz.sig +0 -0
- data/lib/thingfish/processor/mp3.rb +0 -167
@@ -8,14 +8,14 @@ require 'thingfish/processor'
|
|
8
8
|
require 'strelka/httprequest/metadata'
|
9
9
|
|
10
10
|
|
11
|
-
describe Thingfish::Processor, "
|
11
|
+
describe Thingfish::Processor, "SHA256" do
|
12
12
|
|
13
13
|
before( :all ) do
|
14
14
|
Strelka::HTTPRequest.class_eval { include Strelka::HTTPRequest::Metadata }
|
15
15
|
end
|
16
16
|
|
17
17
|
|
18
|
-
let( :processor ) { described_class.create(:
|
18
|
+
let( :processor ) { described_class.create(:sha256) }
|
19
19
|
|
20
20
|
let( :factory ) do
|
21
21
|
Mongrel2::RequestFactory.new(
|
@@ -24,27 +24,26 @@ describe Thingfish::Processor, "MP3" do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
|
27
|
-
it "
|
27
|
+
it "generates a sha256 checksum from an uploaded file" do
|
28
28
|
req = factory.post( '/tf', fixture_data('APIC-1-image.mp3'), 'Content-type' => 'audio/mp3' )
|
29
|
-
|
30
29
|
processor.process_request( req )
|
31
30
|
|
32
|
-
expect( req.metadata ).to
|
31
|
+
expect( req.metadata['checksum'] ).to eq( 'e6b7070cbec90cdc2d8206819d86d100f076f480c9ae19d3eb8f878b3b86f2d6' )
|
33
32
|
end
|
34
33
|
|
35
34
|
|
36
|
-
it "
|
35
|
+
it "generates a sha256 checksum for related resources" do
|
36
|
+
content = "data data data data data"
|
37
37
|
req = factory.post( '/tf', fixture_data('APIC-1-image.mp3'), 'Content-type' => 'audio/mp3' )
|
38
|
+
req.add_related_resource( StringIO.new( content ), {} )
|
38
39
|
|
39
40
|
processor.process_request( req )
|
40
41
|
|
41
42
|
related = req.related_resources
|
42
|
-
|
43
|
-
expect( related.values.first ).
|
44
|
-
to include( 'format' => 'image/jpeg', 'extent' => 7369, 'relationship' => 'album-art' )
|
45
|
-
expect( related.keys.first ).to respond_to( :read )
|
46
|
-
end
|
43
|
+
related_metadata = related.first.last
|
47
44
|
|
45
|
+
expect( related_metadata[:checksum] ).to eq( Digest::SHA256.hexdigest(content) )
|
46
|
+
end
|
48
47
|
end
|
49
48
|
|
50
49
|
# vim: set nosta noet ts=4 sw=4 ft=rspec:
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thingfish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.0
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Granger
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
w8aNA5re5+Rt/Vvjxj5AcEnZnZiz5x959NaddQocX32Z1unHw44pzRNUur1GInfW
|
37
37
|
p4vpx2kUSFSAGjtCbDGTNV2AH8w9OU4xEmNz8c5lyoA=
|
38
38
|
-----END CERTIFICATE-----
|
39
|
-
date: 2016-11-
|
39
|
+
date: 2016-11-14 00:00:00.000000000 Z
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: strelka
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0.
|
61
|
+
version: '0.46'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0.
|
68
|
+
version: '0.46'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: hoe-mercurial
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,20 +122,6 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.7'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: ruby-mp3info
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0.8'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0.8'
|
139
125
|
- !ruby/object:Gem::Dependency
|
140
126
|
name: rdoc
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -182,6 +168,8 @@ extra_rdoc_files:
|
|
182
168
|
- README.rdoc
|
183
169
|
files:
|
184
170
|
- ".simplecov"
|
171
|
+
- ChangeLog
|
172
|
+
- Gemfile
|
185
173
|
- History.rdoc
|
186
174
|
- LICENSE
|
187
175
|
- Manifest.txt
|
@@ -190,6 +178,7 @@ files:
|
|
190
178
|
- Rakefile
|
191
179
|
- bin/tfprocessord
|
192
180
|
- bin/thingfish
|
181
|
+
- etc/mongrel2-config.rb
|
193
182
|
- etc/thingfish.conf.example
|
194
183
|
- lib/strelka/app/metadata.rb
|
195
184
|
- lib/strelka/httprequest/metadata.rb
|
@@ -202,7 +191,7 @@ files:
|
|
202
191
|
- lib/thingfish/metastore/memory.rb
|
203
192
|
- lib/thingfish/mixins.rb
|
204
193
|
- lib/thingfish/processor.rb
|
205
|
-
- lib/thingfish/processor/
|
194
|
+
- lib/thingfish/processor/sha256.rb
|
206
195
|
- lib/thingfish/processordaemon.rb
|
207
196
|
- lib/thingfish/spechelpers.rb
|
208
197
|
- spec/data/APIC-1-image.mp3
|
@@ -217,7 +206,7 @@ files:
|
|
217
206
|
- spec/thingfish/metastore/memory_spec.rb
|
218
207
|
- spec/thingfish/metastore_spec.rb
|
219
208
|
- spec/thingfish/mixins_spec.rb
|
220
|
-
- spec/thingfish/processor/
|
209
|
+
- spec/thingfish/processor/sha256_spec.rb
|
221
210
|
- spec/thingfish/processor_spec.rb
|
222
211
|
- spec/thingfish_spec.rb
|
223
212
|
homepage: http://bitbucket.org/ged/thingfish
|
@@ -238,9 +227,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
238
227
|
version: 2.0.0
|
239
228
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
240
229
|
requirements:
|
241
|
-
- - "
|
230
|
+
- - ">="
|
242
231
|
- !ruby/object:Gem::Version
|
243
|
-
version:
|
232
|
+
version: '0'
|
244
233
|
requirements: []
|
245
234
|
rubyforge_project:
|
246
235
|
rubygems_version: 2.5.1
|
metadata.gz.sig
CHANGED
Binary file
|
@@ -1,167 +0,0 @@
|
|
1
|
-
# -*- ruby -*-
|
2
|
-
#encoding: utf-8
|
3
|
-
|
4
|
-
require 'mp3info'
|
5
|
-
|
6
|
-
require 'thingfish' unless defined?( Thingfish )
|
7
|
-
require 'thingfish/processor' unless defined?( Thingfish::Processor )
|
8
|
-
|
9
|
-
|
10
|
-
# Attach ID3 data to an mp3, along with any embedded album art as a related resource.
|
11
|
-
class Thingfish::Processor::MP3 < Thingfish::Processor
|
12
|
-
extend Loggability
|
13
|
-
|
14
|
-
# Loggability API -- log to the :thingfish logger
|
15
|
-
log_to :thingfish
|
16
|
-
|
17
|
-
# The list of handled types
|
18
|
-
handled_types 'audio/mpeg', 'audio/mpg', 'audio/mp3'
|
19
|
-
|
20
|
-
|
21
|
-
# Null character
|
22
|
-
NULL = "\x0"
|
23
|
-
|
24
|
-
# Attached picture "PIC"
|
25
|
-
# Frame size $xx xx xx
|
26
|
-
# ---- mp3info is 'helpfully' cropping out frame size.
|
27
|
-
# Text encoding $xx
|
28
|
-
# Image format $xx xx xx
|
29
|
-
# Picture type $xx
|
30
|
-
# Description <textstring> $00 (00)
|
31
|
-
# Picture data <binary data>
|
32
|
-
PIC_FORMAT = 'h a3 h Z* a*'
|
33
|
-
|
34
|
-
# Attached picture "APIC"
|
35
|
-
# Text encoding $xx
|
36
|
-
# MIME type <text string> $00
|
37
|
-
# Picture type $xx
|
38
|
-
# Description <text string according to encoding> $00 (00)
|
39
|
-
# Picture data <binary data>
|
40
|
-
APIC_FORMAT = 'h Z* h Z* a*'
|
41
|
-
|
42
|
-
|
43
|
-
### Synchronous processor API -- extract metadata from uploaded MP3s
|
44
|
-
def on_request( request )
|
45
|
-
mp3info = Mp3Info.new( request.body )
|
46
|
-
|
47
|
-
mp3_metadata = self.extract_id3_metadata( mp3info )
|
48
|
-
request.add_metadata( mp3_metadata )
|
49
|
-
|
50
|
-
self.extract_images( mp3info ) do |imageio, metadata|
|
51
|
-
metadata[:title] = "Album art for %s - %s" % mp3_metadata.values_at( 'mp3:artist', 'mp3:title' )
|
52
|
-
request.add_related_resource( imageio, metadata )
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
### Normalize metadata from the MP3Info object and return it as a hash.
|
58
|
-
def extract_id3_metadata( mp3info )
|
59
|
-
self.log.debug "Extracting MP3 metadata"
|
60
|
-
|
61
|
-
mp3_metadata = {
|
62
|
-
'mp3:frequency' => mp3info.samplerate,
|
63
|
-
'mp3:bitrate' => mp3info.bitrate,
|
64
|
-
'mp3:vbr' => mp3info.vbr,
|
65
|
-
'mp3:title' => mp3info.tag.title,
|
66
|
-
'mp3:artist' => mp3info.tag.artist,
|
67
|
-
'mp3:album' => mp3info.tag.album,
|
68
|
-
'mp3:year' => mp3info.tag.year,
|
69
|
-
'mp3:genre' => mp3info.tag.genre,
|
70
|
-
'mp3:tracknum' => mp3info.tag.tracknum,
|
71
|
-
'mp3:comments' => mp3info.tag.comments,
|
72
|
-
}
|
73
|
-
|
74
|
-
# ID3V2 2.2.0 has three-letter tags, so map those if the artist info isn't set
|
75
|
-
if mp3info.hastag2?
|
76
|
-
if mp3_metadata['mp3:artist'].nil?
|
77
|
-
self.log.debug " extracting old-style ID3v2 info" % [mp3info.tag2.version]
|
78
|
-
|
79
|
-
mp3_metadata.merge!({
|
80
|
-
'mp3:title' => mp3info.tag2.TT2,
|
81
|
-
'mp3:artist' => mp3info.tag2.TP1,
|
82
|
-
'mp3:album' => mp3info.tag2.TAL,
|
83
|
-
'mp3:year' => mp3info.tag2.TYE,
|
84
|
-
'mp3:tracknum' => mp3info.tag2.TRK,
|
85
|
-
'mp3:comments' => mp3info.tag2.COM,
|
86
|
-
'mp3:genre' => mp3info.tag2.TCO,
|
87
|
-
})
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
self.log.debug " raw metadata: %p" % [ mp3_metadata ]
|
92
|
-
return sanitize_values( mp3_metadata )
|
93
|
-
end
|
94
|
-
|
95
|
-
|
96
|
-
### Extract image data from ID3 information, supports both APIC (2.3) and the older style
|
97
|
-
### PIC (2.2). Return value is a hash with IO keys and mimetype values.
|
98
|
-
### {
|
99
|
-
### io => { format => 'image/jpeg' }
|
100
|
-
### io2 => { format => 'image/jpeg' }
|
101
|
-
### }
|
102
|
-
def extract_images( mp3info )
|
103
|
-
self.log.debug "Extracting embedded images"
|
104
|
-
raise LocalJumpError, "no block given" unless block_given?
|
105
|
-
|
106
|
-
unless mp3info.hastag2?
|
107
|
-
self.log.debug "...no id3v2 tag, so no embedded images possible."
|
108
|
-
return
|
109
|
-
end
|
110
|
-
|
111
|
-
self.log.debug "...id3v2 tag present..."
|
112
|
-
|
113
|
-
if mp3info.tag2.APIC
|
114
|
-
self.log.debug "...extracting APIC (id3v2.3+) image data."
|
115
|
-
|
116
|
-
images = [ mp3info.tag2.APIC ].flatten
|
117
|
-
images.each do |img|
|
118
|
-
blob, mime = img.unpack( APIC_FORMAT ).values_at( 4, 1 )
|
119
|
-
yield( StringIO.new(blob),
|
120
|
-
:format => mime,
|
121
|
-
:extent => blob.length,
|
122
|
-
:relationship => 'album-art' )
|
123
|
-
end
|
124
|
-
|
125
|
-
elsif mp3info.tag2.PIC
|
126
|
-
self.log.debug "...extracting PIC (id3v2.2) image data."
|
127
|
-
|
128
|
-
images = [ mp3info.tag2.PIC ].flatten
|
129
|
-
images.each do |img|
|
130
|
-
blob, type = img.unpack( PIC_FORMAT ).values_at( 4, 1 )
|
131
|
-
mime = Mongrel2::Config.mimetypes[ ".#{type.downcase}" ] or next
|
132
|
-
yield( StringIO.new(blob),
|
133
|
-
:format => mime,
|
134
|
-
:extent => blob.length,
|
135
|
-
:relationship => 'album-art' )
|
136
|
-
end
|
137
|
-
|
138
|
-
else
|
139
|
-
self.log.debug "...no known image tag types in tags: %p" % [ mp3info.tag2.keys.sort ]
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
#######
|
146
|
-
private
|
147
|
-
#######
|
148
|
-
|
149
|
-
### Strip NULLs from the values of the given +metadata_hash+ and return it.
|
150
|
-
def sanitize_values( metadata_hash )
|
151
|
-
metadata_hash.each do |k,v|
|
152
|
-
case v
|
153
|
-
when String
|
154
|
-
metadata_hash[k] = v.chomp(NULL).strip
|
155
|
-
when Array
|
156
|
-
metadata_hash[k] = v.collect {|vv| vv.chomp(NULL).strip }
|
157
|
-
when Numeric, TrueClass, FalseClass
|
158
|
-
# No-op
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
return metadata_hash.delete_if {|_,v| v.nil? }
|
163
|
-
end
|
164
|
-
|
165
|
-
|
166
|
-
end # class Thingfish::Processor::MP3
|
167
|
-
|