meme_captain 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/config.ru CHANGED
@@ -1,5 +1,10 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
2
 
3
+ require 'rack'
4
+
3
5
  require 'meme_captain'
4
6
 
7
+ use Rack::ConditionalGet
8
+ use Rack::Sendfile
9
+
5
10
  run MemeCaptain::Server
@@ -0,0 +1,15 @@
1
+ module MemeCaptain
2
+
3
+ # A Rack body for an object on the filesystem.
4
+ class FileBody
5
+
6
+ def initialize(path); @to_path = path; end
7
+
8
+ def each
9
+ open(to_path, 'rb') { |f| yield f.read(8192) until f.eof? }
10
+ end
11
+
12
+ attr_reader :to_path
13
+ end
14
+
15
+ end
@@ -5,32 +5,60 @@ module MemeCaptain
5
5
 
6
6
  def initialize(root_dir); @root_dir = root_dir; end
7
7
 
8
- # Get data from cache.
8
+ # Get the data of a file in the cache.
9
9
  #
10
- # On cache miss, if block given call block to get data from source and
10
+ # On cache miss, if block given, call block to get data from source and
11
11
  # cache it. If no block given return nil on cache miss.
12
- def get(id)
13
- file_path = id_path(id)
12
+ #
13
+ # If suffixes are passed in, loop through them and search for base id +
14
+ # suffix on filesystem. Return the data of the first found.
15
+ def get_data(id, suffixes=[''])
16
+ suffixes.each do |suffix|
17
+ file_path = id_path(id, suffix)
18
+ return open(file_path, 'rb') { |f| f.read } if File.exist?(file_path)
19
+ end
20
+
21
+ # not found in cache
22
+ if block_given?
23
+ data = yield
24
+ put(id, data)
25
+ data
26
+ end
27
+ end
14
28
 
15
- if File.exist?(file_path)
16
- open(file_path, 'rb') { |f| f.read }
17
- else
18
- put(id, yield) if block_given?
29
+ # Get the path of a file in the cache.
30
+ #
31
+ # On cache miss, if block given, call block to get data from source and
32
+ # cache it. If no block given return nil on cache miss.
33
+ #
34
+ # If suffixes are passed in, loop through them and search for base id +
35
+ # suffix on filesystem. Return the first found.
36
+ def get_path(id, suffixes=[''])
37
+ suffixes.each do |suffix|
38
+ file_path = id_path(id, suffix)
39
+ return file_path if File.exist?(file_path)
19
40
  end
41
+
42
+ # not found in cache
43
+ put(id, yield) if block_given?
20
44
  end
21
45
 
22
- # Put data in the cache and return it.
46
+ # Put data in the cache and return its path.
23
47
  def put(id, data)
24
- open(id_path(id), 'w') do |f|
48
+ mime_type = MemeCaptain.mime_type(data)
49
+ file_path = id_path(id, ".#{mime_type.extensions[0]}")
50
+
51
+ open(file_path, 'w') do |f|
25
52
  f.flock(File::LOCK_EX)
26
53
  f.write(data)
27
54
  f.flock(File::LOCK_UN)
28
55
  end
29
- data
56
+ file_path
30
57
  end
31
58
 
32
- def id_path(id)
33
- File.join(root_dir, File.expand_path(id, '/'))
59
+ # Get the cache file path for an id with optional suffix added.
60
+ def id_path(id, suffix=nil)
61
+ File.join(root_dir, File.expand_path(id, '/')) + suffix.to_s
34
62
  end
35
63
 
36
64
  attr_reader :root_dir
@@ -1,16 +1,20 @@
1
+ require 'mime/types'
2
+
1
3
  module MemeCaptain
2
4
 
3
5
  module_function
4
6
 
5
- # Determine content type from blob of image data.
6
- def content_type(img_data)
7
- if img_data[0,2].unpack('H4')[0] == 'ffd8'
7
+ # Determine mime type from blob of image data.
8
+ def mime_type(img_data)
9
+ mime_type_s = if img_data[0,2].unpack('H4')[0] == 'ffd8'
8
10
  'image/jpeg'
9
11
  elsif img_data[0,8].unpack('H16')[0] == '89504e470d0a1a0a'
10
12
  'image/png'
11
13
  elsif %w{474946383961 474946383761}.include?(img_data[0,6].unpack('H12')[0])
12
14
  'image/gif'
13
15
  end
16
+
17
+ MIME::Types[mime_type_s][0]
14
18
  end
15
19
 
16
20
  end
@@ -9,6 +9,8 @@ module MemeCaptain
9
9
 
10
10
  class Server < Sinatra::Base
11
11
 
12
+ ImageExts = %w{.jpeg .gif .png}
13
+
12
14
  get '/' do
13
15
  @img_tag = if params[:u]
14
16
  "<img src=\"#{h request.fullpath.sub(%r{^/}, '/i')}\" />"
@@ -29,22 +31,22 @@ module MemeCaptain
29
31
  @source_cache ||= MemeCaptain::FilesystemCache.new('img_cache/source')
30
32
 
31
33
  processed_id = Digest::SHA1.hexdigest(params.sort.map(&:join).join)
32
- processed_img_data = @processed_cache.get(processed_id) {
34
+ processed_cache_path = @processed_cache.get_path(processed_id, ImageExts) {
33
35
  source_id = Digest::SHA1.hexdigest(params[:u])
34
- source_img_data = @source_cache.get(source_id) {
36
+ source_img_data = @source_cache.get_data(source_id, ImageExts) {
35
37
  Curl::Easy.perform(params[:u]).body_str
36
38
  }
39
+
37
40
  MemeCaptain.meme(source_img_data, params[:tt], params[:tb]).to_blob {
38
41
  self.quality = 100
39
42
  }
40
43
  }
41
44
 
42
45
  headers = {
43
- 'Content-Type' => MemeCaptain.content_type(processed_img_data),
44
- 'ETag' => "\"#{Digest::SHA1.hexdigest(processed_img_data)}\"",
46
+ 'Content-Type' => MIME::Types.type_for(processed_cache_path)[0].to_s,
45
47
  }
46
48
 
47
- [ 200, headers, processed_img_data ]
49
+ [ 200, headers, MemeCaptain::FileBody.new(processed_cache_path) ]
48
50
  end
49
51
 
50
52
  helpers do
data/lib/meme_captain.rb CHANGED
@@ -1,4 +1,5 @@
1
- require 'meme_captain/content_type'
1
+ require 'meme_captain/file_body'
2
2
  require 'meme_captain/meme'
3
+ require 'meme_captain/mime_type'
3
4
  require 'meme_captain/server'
4
5
  require 'meme_captain/filesystem_cache'
data/meme_captain.gemspec CHANGED
@@ -4,7 +4,7 @@ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'meme_captain'
7
- s.version = '0.0.2'
7
+ s.version = '0.0.3'
8
8
  s.summary = 'create meme images'
9
9
  s.description = s.summary
10
10
  s.homepage = 'https://github.com/mmb/meme_captain'
@@ -15,6 +15,8 @@ Gem::Specification.new do |s|
15
15
 
16
16
  %w{
17
17
  curb
18
+ mime-types
19
+ rack
18
20
  rmagick
19
21
  sinatra
20
22
  }.each { |g| s.add_dependency g }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meme_captain
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matthew M. Boedicker
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-20 00:00:00 -04:00
18
+ date: 2011-04-22 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -33,7 +33,7 @@ dependencies:
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
- name: rmagick
36
+ name: mime-types
37
37
  prerelease: false
38
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
39
  none: false
@@ -47,7 +47,7 @@ dependencies:
47
47
  type: :runtime
48
48
  version_requirements: *id002
49
49
  - !ruby/object:Gem::Dependency
50
- name: sinatra
50
+ name: rack
51
51
  prerelease: false
52
52
  requirement: &id003 !ruby/object:Gem::Requirement
53
53
  none: false
@@ -60,6 +60,34 @@ dependencies:
60
60
  version: "0"
61
61
  type: :runtime
62
62
  version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: rmagick
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :runtime
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: sinatra
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :runtime
90
+ version_requirements: *id005
63
91
  description: create meme images
64
92
  email:
65
93
  - matthewm@boedicker.org
@@ -77,9 +105,10 @@ files:
77
105
  - img_cache/processed/.gitignore
78
106
  - img_cache/source/.gitignore
79
107
  - lib/meme_captain.rb
80
- - lib/meme_captain/content_type.rb
108
+ - lib/meme_captain/file_body.rb
81
109
  - lib/meme_captain/filesystem_cache.rb
82
110
  - lib/meme_captain/meme.rb
111
+ - lib/meme_captain/mime_type.rb
83
112
  - lib/meme_captain/server.rb
84
113
  - meme_captain.gemspec
85
114
  - views/index.erb