thingfish 0.5.0.pre20161103181816 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,14 +8,14 @@ require 'thingfish/processor'
8
8
  require 'strelka/httprequest/metadata'
9
9
 
10
10
 
11
- describe Thingfish::Processor, "MP3" do
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(:mp3) }
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 "extracts metadata from uploaded MP3 ID3 tags" do
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 include( 'mp3:artist', 'mp3:bitrate', 'mp3:comments' )
31
+ expect( req.metadata['checksum'] ).to eq( 'e6b7070cbec90cdc2d8206819d86d100f076f480c9ae19d3eb8f878b3b86f2d6' )
33
32
  end
34
33
 
35
34
 
36
- it "attaches album art as a related resource" do
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
- expect( related.size ).to eq( 1 )
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.pre20161103181816
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-04 00:00:00.000000000 Z
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.43'
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.43'
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/mp3.rb
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/mp3_spec.rb
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: 1.3.1
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
-