thingfish 0.5.0.pre20161103181816 → 0.8.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.md +48 -0
- data/{README.rdoc → README.md} +40 -26
- data/Rakefile +4 -88
- data/bin/thingfish +1 -1
- data/lib/strelka/app/metadata.rb +1 -1
- data/lib/strelka/apps.rb +9 -0
- data/lib/strelka/httprequest/metadata.rb +1 -1
- data/lib/thingfish.rb +2 -13
- data/lib/thingfish/behaviors.rb +1 -1
- data/lib/thingfish/datastore.rb +1 -1
- data/lib/thingfish/datastore/memory.rb +1 -1
- data/lib/thingfish/handler.rb +94 -53
- data/lib/thingfish/metastore.rb +1 -1
- data/lib/thingfish/metastore/memory.rb +1 -1
- data/lib/thingfish/mixins.rb +1 -1
- data/lib/thingfish/processor.rb +1 -1
- data/lib/thingfish/processor/sha256.rb +51 -0
- data/lib/thingfish/spechelpers.rb +1 -1
- data/spec/helpers.rb +19 -12
- data/spec/thingfish/datastore/memory_spec.rb +1 -1
- data/spec/thingfish/datastore_spec.rb +1 -1
- data/spec/thingfish/handler_spec.rb +235 -201
- data/spec/thingfish/metastore/memory_spec.rb +1 -1
- data/spec/thingfish/metastore_spec.rb +1 -1
- data/spec/thingfish/mixins_spec.rb +1 -1
- data/spec/thingfish/processor/{mp3_spec.rb → sha256_spec.rb} +10 -11
- data/spec/thingfish/processor_spec.rb +1 -1
- data/spec/thingfish_spec.rb +1 -1
- metadata +61 -141
- metadata.gz.sig +0 -0
- data/History.rdoc +0 -5
- data/Manifest.txt +0 -44
- data/Procfile +0 -4
- data/bin/tfprocessord +0 -6
- data/etc/thingfish.conf.example +0 -26
- data/lib/thingfish/processor/mp3.rb +0 -167
- data/lib/thingfish/processordaemon.rb +0 -16
data/Procfile
DELETED
data/bin/tfprocessord
DELETED
data/etc/thingfish.conf.example
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
---
|
2
|
-
logging:
|
3
|
-
__default__: debug STDERR
|
4
|
-
thingfish: info (color)
|
5
|
-
|
6
|
-
# Thingfish specific configuration.
|
7
|
-
#
|
8
|
-
thingfish:
|
9
|
-
datastore: memory
|
10
|
-
metastore: memory
|
11
|
-
|
12
|
-
# The path to the Mongrel2 config database.
|
13
|
-
#
|
14
|
-
mongrel2:
|
15
|
-
configdb: example/mongrel2.sqlite
|
16
|
-
|
17
|
-
# Strelka configuration knobs that influence Thingfish's handler.
|
18
|
-
#
|
19
|
-
app:
|
20
|
-
devmode: false
|
21
|
-
app_glob_pattern: '{apps,handlers}/**/*'
|
22
|
-
local_data_dirs: data/*
|
23
|
-
multipartparser:
|
24
|
-
bufsize: 524288
|
25
|
-
spooldir: /var/folders/1f/6ymhh79s0n3gjdw16fj7tp480000gp/T/strelka-mimeparts
|
26
|
-
|
@@ -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
|
-
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# -*- ruby -*-
|
2
|
-
#encoding: utf-8
|
3
|
-
|
4
|
-
require 'zmq'
|
5
|
-
require 'configurability'
|
6
|
-
require 'loggability'
|
7
|
-
|
8
|
-
require 'thingfish' unless defined?( Thingfish )
|
9
|
-
|
10
|
-
|
11
|
-
# Currently just a placeholder for what will eventually be the runner for
|
12
|
-
# async processors.
|
13
|
-
class Thingfish::ProcessorDaemon
|
14
|
-
end # class Thingfish::ProcessorDaemon
|
15
|
-
|
16
|
-
|