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.
@@ -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
-