meme_captain 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +4 -0
- data/README.md +0 -45
- data/lib/meme_captain.rb +0 -6
- data/lib/meme_captain/caption.rb +6 -4
- data/lib/meme_captain/caption_choice.rb +3 -1
- data/lib/meme_captain/image_list.rb +0 -5
- data/lib/meme_captain/text_pos.rb +8 -6
- data/lib/meme_captain/version.rb +1 -1
- data/meme_captain.gemspec +5 -18
- metadata +2 -181
- data/config.ru +0 -50
- data/doc/lightweight_front_end.md +0 -64
- data/doc/setup.md +0 -13
- data/lib/meme_captain/image_list/cache.rb +0 -49
- data/lib/meme_captain/image_list/fetch.rb +0 -28
- data/lib/meme_captain/image_list/fetch_error.rb +0 -17
- data/lib/meme_captain/image_list/source_image.rb +0 -30
- data/lib/meme_captain/meme_data.rb +0 -33
- data/lib/meme_captain/norm_params.rb +0 -92
- data/lib/meme_captain/pretty_format.rb +0 -12
- data/lib/meme_captain/server.rb +0 -303
- data/lib/meme_captain/source_fetch_fail.rb +0 -28
- data/lib/meme_captain/upload.rb +0 -30
- data/public/css/screen.css +0 -80
- data/public/favicon.ico +0 -0
- data/public/js/fabric.min.js +0 -4
- data/public/js/jquery-1.7.2.min.js +0 -4
- data/public/js/meme_captain.js +0 -391
- data/public/source_images.json +0 -234
- data/public/thumbs.jpg +0 -0
- data/public/thumbs_1330486916.jpg +0 -0
- data/public/thumbs_1333591668.jpg +0 -0
- data/public/thumbs_1334189407.jpg +0 -0
- data/public/thumbs_1334973608.jpg +0 -0
- data/public/thumbs_1336623277.jpg +0 -0
- data/public/thumbs_1336624196.jpg +0 -0
- data/public/thumbs_1339811279.jpg +0 -0
- data/public/tmp/.gitignore +0 -0
- data/script/thumb_sprites.rb +0 -76
- data/spec/image_list/fetch_spec.rb +0 -33
- data/spec/norm_params_spec.rb +0 -223
- data/spec/pretty_format_spec.rb +0 -9
- data/views/404.erb +0 -17
- data/views/index.erb +0 -130
- data/watermark.png +0 -0
@@ -1,64 +0,0 @@
|
|
1
|
-
If you want to host your own custom Meme Captain site but do not want to set
|
2
|
-
up the ruby backend you can use the memecaptain.com backend. In this scenario,
|
3
|
-
the HTML, Javscript and CSS are hosted on your web server and the meme images
|
4
|
-
are created on and hosted on memecaptain.com.
|
5
|
-
|
6
|
-
This is an option if you are on shared hosting and do not have access to
|
7
|
-
ruby or MongoDB or do not want to deal with setting them up.
|
8
|
-
|
9
|
-
Download the files at these locations and save them in your document root:
|
10
|
-
|
11
|
-
* http://memecaptain.com/
|
12
|
-
* http://memecaptain.com/css/screen.css
|
13
|
-
* http://memecaptain.com/js/fabric.min.js
|
14
|
-
* http://memecaptain.com/js/meme_captain.js
|
15
|
-
* http://memecaptain.com/source_images.json
|
16
|
-
|
17
|
-
The css in js should go in css and js directories in your document root so
|
18
|
-
that they match the url paths.
|
19
|
-
|
20
|
-
Find this line in js/meme_captain.js
|
21
|
-
|
22
|
-
```
|
23
|
-
genUrl = '/g',
|
24
|
-
```
|
25
|
-
|
26
|
-
and change it to
|
27
|
-
|
28
|
-
```
|
29
|
-
genUrl = 'http://memecaptain.com/g',
|
30
|
-
```
|
31
|
-
|
32
|
-
# Changing the Default Source Images
|
33
|
-
|
34
|
-
The source image thumbnails that show up on the page are driven by a JSON
|
35
|
-
description and a single image that contain CSS sprites. The JSON and image
|
36
|
-
must be regenerated to change them.
|
37
|
-
|
38
|
-
The rmagick ruby gem must be installed:
|
39
|
-
|
40
|
-
```sh
|
41
|
-
gem install rmagick
|
42
|
-
```
|
43
|
-
|
44
|
-
Get and run the script:
|
45
|
-
|
46
|
-
```sh
|
47
|
-
wget https://raw.github.com/mmb/meme_captain/master/script/thumb_sprites.rb
|
48
|
-
RUBYOPT='r rubygems'
|
49
|
-
ruby thumb_sprites.rb -u URL_ROOT -s SOURCE_URL_PREFIX SOURCE_IMAGE_PATH/*
|
50
|
-
```
|
51
|
-
|
52
|
-
SOURCE_IMAGE_PATH is the directory where the source images are stored.
|
53
|
-
URL_ROOT is the root url of the Meme Captain installation. SOURCE_URL_PREFIX
|
54
|
-
is the part between the root url and the image filenames in the image urls.
|
55
|
-
|
56
|
-
For example if the images are stored in /var/www/meme.com/source and the
|
57
|
-
url root is http://meme.com/, use:
|
58
|
-
|
59
|
-
```sh
|
60
|
-
ruby thumb_sprites.rb -u http://meme.com/ -s source/ /var/www/meme.com/source/*
|
61
|
-
```
|
62
|
-
|
63
|
-
Copy the generated source_images.json and thumbs_xxx.jpg files to the Meme
|
64
|
-
Captain document root.
|
data/doc/setup.md
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# Requirements
|
2
|
-
|
3
|
-
* a Ruby/Rack web application environment (such as
|
4
|
-
[Passenger](http://www.modrails.com/))
|
5
|
-
|
6
|
-
* Ruby gem dependencies (see the gemspec)
|
7
|
-
|
8
|
-
* [MongoDB](http://www.mongodb.org/)
|
9
|
-
|
10
|
-
You will most likely need a dedicated or virtual private server to run
|
11
|
-
MongoDB as most shared hosting does not support it. See the lightweight front
|
12
|
-
end document for how host the static HTML/CSS/Javascript only and use
|
13
|
-
memecaptain.com for the backend.
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'digest/sha1'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'mime/types'
|
4
|
-
|
5
|
-
module MemeCaptain
|
6
|
-
|
7
|
-
module ImageList
|
8
|
-
|
9
|
-
# Mix-in for Magick::ImageList to add saving to the filesystem based on a
|
10
|
-
# hash.
|
11
|
-
module Cache
|
12
|
-
|
13
|
-
# Get the extension for this image.
|
14
|
-
def extension
|
15
|
-
{
|
16
|
-
'image/jpeg' => 'jpg',
|
17
|
-
}[mime_type] || MIME::Types[mime_type][0].extensions[0]
|
18
|
-
end
|
19
|
-
|
20
|
-
# Store this image in the filesystem and return its path.
|
21
|
-
def cache(hash_base, dir)
|
22
|
-
hashe = Digest::SHA1.hexdigest(hash_base)
|
23
|
-
|
24
|
-
cache_dir = File.join(dir, hashe[0,3])
|
25
|
-
FileUtils.mkdir_p cache_dir
|
26
|
-
|
27
|
-
file_part = hashe[3..-1]
|
28
|
-
fs_path = File.join(cache_dir, "#{file_part}.#{extension}")
|
29
|
-
|
30
|
-
# If there is a collision add 0's until the filename is unique.
|
31
|
-
zeroes = 0
|
32
|
-
while File.exist? fs_path
|
33
|
-
zeroes += 1
|
34
|
-
fs_path = File.join(cache_dir,
|
35
|
-
"#{file_part}#{'0' * zeroes}.#{extension}")
|
36
|
-
end
|
37
|
-
|
38
|
-
write(fs_path) {
|
39
|
-
self.quality = 100
|
40
|
-
}
|
41
|
-
|
42
|
-
fs_path
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'curb'
|
2
|
-
|
3
|
-
module MemeCaptain
|
4
|
-
|
5
|
-
module ImageList
|
6
|
-
|
7
|
-
# Mix-in for Magick::ImageList to add loading from a URL.
|
8
|
-
module Fetch
|
9
|
-
|
10
|
-
# Load this image from a URL.
|
11
|
-
def fetch!(url)
|
12
|
-
curl = Curl::Easy.perform(url) do |c|
|
13
|
-
c.useragent = 'Meme Captain http://memecaptain.com/'
|
14
|
-
c.follow_location = true
|
15
|
-
c.max_redirects = 3
|
16
|
-
end
|
17
|
-
unless curl.response_code == 200
|
18
|
-
raise FetchError.new(curl.response_code)
|
19
|
-
end
|
20
|
-
|
21
|
-
from_blob curl.body_str
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module MemeCaptain
|
2
|
-
|
3
|
-
module ImageList
|
4
|
-
|
5
|
-
# Error for source image fetch failures.
|
6
|
-
class FetchError < StandardError
|
7
|
-
|
8
|
-
def initialize(response_code)
|
9
|
-
@response_code = response_code
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_accessor :response_code
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'RMagick'
|
2
|
-
|
3
|
-
module MemeCaptain
|
4
|
-
|
5
|
-
module ImageList
|
6
|
-
|
7
|
-
# Source image for meme generation.
|
8
|
-
class SourceImage < Magick::ImageList
|
9
|
-
include Cache
|
10
|
-
include Fetch
|
11
|
-
include Watermark
|
12
|
-
|
13
|
-
# Shrink image if necessary and add watermark.
|
14
|
-
def prepare!(max_side, watermark_img)
|
15
|
-
auto_orient!
|
16
|
-
|
17
|
-
if size == 1 and (columns > max_side or rows > max_side)
|
18
|
-
resize_to_fit! max_side
|
19
|
-
end
|
20
|
-
|
21
|
-
watermark_mc watermark_img
|
22
|
-
|
23
|
-
strip!
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'mongo_mapper'
|
2
|
-
|
3
|
-
module MemeCaptain
|
4
|
-
|
5
|
-
class MemeData
|
6
|
-
include MongoMapper::Document
|
7
|
-
|
8
|
-
set_collection_name 'meme'
|
9
|
-
|
10
|
-
key :meme_id, String
|
11
|
-
key :fs_path, String
|
12
|
-
key :mime_type, String
|
13
|
-
key :size, Integer
|
14
|
-
|
15
|
-
key :source_url, String
|
16
|
-
key :source_fs_path, String
|
17
|
-
key :texts, Array
|
18
|
-
|
19
|
-
key :request_count, Integer
|
20
|
-
key :last_request, Time
|
21
|
-
|
22
|
-
key :creator_ip, String
|
23
|
-
|
24
|
-
timestamps!
|
25
|
-
|
26
|
-
def requested!
|
27
|
-
increment :request_count => 1
|
28
|
-
set :last_request => Time.now
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
@@ -1,92 +0,0 @@
|
|
1
|
-
module MemeCaptain
|
2
|
-
|
3
|
-
# Normalize query string parameters.
|
4
|
-
#
|
5
|
-
# Provide defaults, do some basic validation and convert some parameters
|
6
|
-
# to floats or integers.
|
7
|
-
class NormParams
|
8
|
-
|
9
|
-
def initialize(params={})
|
10
|
-
@u = ''
|
11
|
-
|
12
|
-
@t1 = ''
|
13
|
-
@t2 = ''
|
14
|
-
|
15
|
-
@t1x = 0.05
|
16
|
-
@t1y = 0
|
17
|
-
@t1w = 0.9
|
18
|
-
@t1h = 0.25
|
19
|
-
|
20
|
-
@t2x = 0.05
|
21
|
-
@t2y = 0.75
|
22
|
-
@t2w = 0.9
|
23
|
-
@t2h = 0.25
|
24
|
-
|
25
|
-
load params
|
26
|
-
end
|
27
|
-
|
28
|
-
# Load query string parameters.
|
29
|
-
#
|
30
|
-
# Do some basic validation and convert some parameters to floats or
|
31
|
-
# integers.
|
32
|
-
def load(params)
|
33
|
-
params.select { |k,v|
|
34
|
-
[
|
35
|
-
:u,
|
36
|
-
:t1,
|
37
|
-
:t2,
|
38
|
-
].include? k.to_sym }.each do |k,v|
|
39
|
-
send "#{k}=", v.to_s
|
40
|
-
end
|
41
|
-
|
42
|
-
params.select { |k,v|
|
43
|
-
[
|
44
|
-
:t1x,
|
45
|
-
:t1y,
|
46
|
-
:t1w,
|
47
|
-
:t1h,
|
48
|
-
|
49
|
-
:t2x,
|
50
|
-
:t2y,
|
51
|
-
:t2w,
|
52
|
-
:t2h,
|
53
|
-
].include?(k.to_sym) and !v.to_s.empty? }.each do |k,v|
|
54
|
-
send "#{k}=", convert_metric(v)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Return a sorted string representation of the fields.
|
59
|
-
def signature
|
60
|
-
instance_variables.sort.map { |v|
|
61
|
-
name = v[1..-1] # remove @
|
62
|
-
"#{name}#{instance_variable_get(v)}"
|
63
|
-
}.join
|
64
|
-
end
|
65
|
-
|
66
|
-
attr_accessor :u
|
67
|
-
|
68
|
-
attr_accessor :t1
|
69
|
-
attr_accessor :t2
|
70
|
-
|
71
|
-
attr_accessor :t1x
|
72
|
-
attr_accessor :t1y
|
73
|
-
attr_accessor :t1w
|
74
|
-
attr_accessor :t1h
|
75
|
-
|
76
|
-
attr_accessor :t2x
|
77
|
-
attr_accessor :t2y
|
78
|
-
attr_accessor :t2w
|
79
|
-
attr_accessor :t2h
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
# Convert a metric string to a float or integer.
|
84
|
-
#
|
85
|
-
# Expects a string.
|
86
|
-
def convert_metric(metric)
|
87
|
-
metric.index('.') ? metric.to_f : metric.to_i
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
data/lib/meme_captain/server.rb
DELETED
@@ -1,303 +0,0 @@
|
|
1
|
-
require 'digest/sha1'
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
require 'rack'
|
5
|
-
require 'sinatra/base'
|
6
|
-
|
7
|
-
module MemeCaptain
|
8
|
-
|
9
|
-
class Server < Sinatra::Base
|
10
|
-
|
11
|
-
set :root, File.expand_path(File.join('..', '..'), File.dirname(__FILE__))
|
12
|
-
set :source_img_max_side, 800
|
13
|
-
set :upload_prefix, 'up/'
|
14
|
-
set :watermark, Magick::ImageList.new(File.expand_path(
|
15
|
-
File.join('..', '..', 'watermark.png'), File.dirname(__FILE__)))
|
16
|
-
|
17
|
-
# uncomment this to allow other sites to use this site's backend for
|
18
|
-
# generating images, used to allow third-party static only sites
|
19
|
-
# to generate images using memecaptain.com
|
20
|
-
|
21
|
-
# set :protection, :except => :json_csrf
|
22
|
-
|
23
|
-
get '/' do
|
24
|
-
@u = params[:u]
|
25
|
-
|
26
|
-
@t1 = params[:t1]
|
27
|
-
@t1x = params[:t1x]
|
28
|
-
@t1y = params[:t1y]
|
29
|
-
@t1w = params[:t1w]
|
30
|
-
@t1h = params[:t1h]
|
31
|
-
|
32
|
-
@t2 = params[:t2]
|
33
|
-
@t2x = params[:t2x]
|
34
|
-
@t2y = params[:t2y]
|
35
|
-
@t2w = params[:t2w]
|
36
|
-
@t2h = params[:t2h]
|
37
|
-
|
38
|
-
@root_url = url('/')
|
39
|
-
|
40
|
-
erb :index
|
41
|
-
end
|
42
|
-
|
43
|
-
def normalize_params(p)
|
44
|
-
result = NormParams.new(p)
|
45
|
-
|
46
|
-
# if the id of an existing meme is passed in as the source url, use the
|
47
|
-
# source image of that meme for the source image
|
48
|
-
if result.u[%r{^[a-f0-9]+\.(?:gif|jpg|png)$}]
|
49
|
-
if existing_as_source = MemeData.find_by_meme_id(result.u)
|
50
|
-
result.u = existing_as_source.source_url
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
result
|
55
|
-
end
|
56
|
-
|
57
|
-
def gen(p)
|
58
|
-
logger.debug "params:\n#{MemeCaptain.pretty_format(p)}"
|
59
|
-
norm_params = normalize_params(p)
|
60
|
-
logger.debug 'normalized params:'
|
61
|
-
logger.debug(MemeCaptain.pretty_format(norm_params))
|
62
|
-
|
63
|
-
if existing = MemeData.first(
|
64
|
-
:source_url => norm_params.u,
|
65
|
-
|
66
|
-
'texts.0.text' => norm_params.t1,
|
67
|
-
'texts.0.x' => norm_params.t1x,
|
68
|
-
'texts.0.y' => norm_params.t1y,
|
69
|
-
'texts.0.w' => norm_params.t1w,
|
70
|
-
'texts.0.h' => norm_params.t1h,
|
71
|
-
|
72
|
-
'texts.1.text' => norm_params.t2,
|
73
|
-
'texts.1.x' => norm_params.t2x,
|
74
|
-
'texts.1.y' => norm_params.t2y,
|
75
|
-
'texts.1.w' => norm_params.t2w,
|
76
|
-
'texts.1.h' => norm_params.t2h
|
77
|
-
)
|
78
|
-
logger.debug 'found existing meme:'
|
79
|
-
logger.debug(MemeCaptain.pretty_format(existing))
|
80
|
-
existing
|
81
|
-
else
|
82
|
-
if same_source = MemeData.find_by_source_url(norm_params.u)
|
83
|
-
logger.debug 'found existing source image'
|
84
|
-
source_fs_path = same_source.source_fs_path
|
85
|
-
elsif (norm_params.u.index(settings.upload_prefix) == 0) and
|
86
|
-
(upload = Upload.find_by_upload_id(
|
87
|
-
norm_params.u[settings.upload_prefix.size..-1]))
|
88
|
-
|
89
|
-
logger.debug 'source image is upload:'
|
90
|
-
logger.debug MemeCaptain.pretty_format(upload)
|
91
|
-
source_fs_path = upload.fs_path
|
92
|
-
else
|
93
|
-
if source_fetch_fail = SourceFetchFail.find_by_url(norm_params.u)
|
94
|
-
logger.debug 'skipping fetch of previously failed source image:'
|
95
|
-
logger.debug(MemeCaptain.pretty_format(source_fetch_fail))
|
96
|
-
source_fetch_fail.requested!
|
97
|
-
halt 500, 'Error loading source image url'
|
98
|
-
else
|
99
|
-
source_img = ImageList::SourceImage.new
|
100
|
-
begin
|
101
|
-
logger.debug "fetch source image: #{norm_params.u}"
|
102
|
-
source_img.fetch! norm_params.u
|
103
|
-
rescue => error
|
104
|
-
new_source_fetch_fail = SourceFetchFail.new(
|
105
|
-
:attempt_count => 1,
|
106
|
-
:orig_ip => request.ip,
|
107
|
-
:response_code => error.respond_to?(:response_code) ?
|
108
|
-
error.response_code : nil,
|
109
|
-
:url => norm_params.u
|
110
|
-
)
|
111
|
-
logger.debug 'source image fetch failed:'
|
112
|
-
logger.debug(MemeCaptain.pretty_format(new_source_fetch_fail))
|
113
|
-
new_source_fetch_fail.save!
|
114
|
-
halt 500, 'Error loading source image url'
|
115
|
-
end
|
116
|
-
source_img.prepare! settings.source_img_max_side, settings.watermark
|
117
|
-
source_fs_path = source_img.cache(norm_params.u, 'source_cache')
|
118
|
-
source_img.each { |frame| frame.destroy! }
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
logger.debug "source image filesystem path: #{source_fs_path}"
|
123
|
-
|
124
|
-
open(source_fs_path, 'rb') do |source_io|
|
125
|
-
t1 = TextPos.new(norm_params.t1, norm_params.t1x, norm_params.t1y,
|
126
|
-
norm_params.t1w, norm_params.t1h)
|
127
|
-
|
128
|
-
t2 = TextPos.new(norm_params.t2, norm_params.t2x, norm_params.t2y,
|
129
|
-
norm_params.t2w, norm_params.t2h)
|
130
|
-
|
131
|
-
meme_img = MemeCaptain.meme(source_io, [t1, t2])
|
132
|
-
meme_img.extend ImageList::Cache
|
133
|
-
|
134
|
-
# convert source images in formats other than jpeg, gif or png
|
135
|
-
# to png
|
136
|
-
unless %w{JPEG GIF PNG}.include?(meme_img.format)
|
137
|
-
meme_img.format = 'PNG'
|
138
|
-
end
|
139
|
-
|
140
|
-
# convert non-animated gifs to png
|
141
|
-
if meme_img.format == 'GIF' and meme_img.size == 1
|
142
|
-
meme_img.format = 'PNG'
|
143
|
-
end
|
144
|
-
|
145
|
-
sig = norm_params.signature
|
146
|
-
meme_hash = Digest::SHA1.hexdigest(sig)
|
147
|
-
|
148
|
-
meme_id = nil
|
149
|
-
(6..meme_hash.size).each do |len|
|
150
|
-
meme_id = "#{meme_hash[0,len]}.#{meme_img.extension}"
|
151
|
-
break unless MemeData.where(:meme_id => meme_id).count > 0
|
152
|
-
end
|
153
|
-
|
154
|
-
meme_fs_path = meme_img.cache(sig, File.join('public', 'meme'))
|
155
|
-
|
156
|
-
logger.debug "meme filesystem path: #{meme_fs_path}"
|
157
|
-
|
158
|
-
meme_img.write(meme_fs_path) {
|
159
|
-
self.quality = 100
|
160
|
-
}
|
161
|
-
|
162
|
-
meme_data = MemeData.new(
|
163
|
-
:meme_id => meme_id,
|
164
|
-
:fs_path => meme_fs_path,
|
165
|
-
:mime_type => meme_img.mime_type,
|
166
|
-
:size => File.size(meme_fs_path),
|
167
|
-
|
168
|
-
:source_url => norm_params.u,
|
169
|
-
:source_fs_path => source_fs_path,
|
170
|
-
|
171
|
-
:texts => [{
|
172
|
-
:text => norm_params.t1,
|
173
|
-
:x => norm_params.t1x,
|
174
|
-
:y => norm_params.t1y,
|
175
|
-
:w => norm_params.t1w,
|
176
|
-
:h => norm_params.t1h,
|
177
|
-
}, {
|
178
|
-
:text => norm_params.t2,
|
179
|
-
:x => norm_params.t2x,
|
180
|
-
:y => norm_params.t2y,
|
181
|
-
:w => norm_params.t2w,
|
182
|
-
:h => norm_params.t2h,
|
183
|
-
}],
|
184
|
-
|
185
|
-
:request_count => 0,
|
186
|
-
|
187
|
-
:creator_ip => request.ip
|
188
|
-
)
|
189
|
-
|
190
|
-
meme_img.each { |frame| frame.destroy! }
|
191
|
-
|
192
|
-
logger.debug "meme data:\n#{MemeCaptain.pretty_format(meme_data)}"
|
193
|
-
|
194
|
-
meme_data.save! :safe => true
|
195
|
-
|
196
|
-
meme_data
|
197
|
-
end
|
198
|
-
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
get '/g' do
|
203
|
-
begin
|
204
|
-
meme_data = gen(params)
|
205
|
-
|
206
|
-
[200, { 'Content-Type' => 'application/json' }, {
|
207
|
-
'imageUrl' => url("/#{meme_data.meme_id}"),
|
208
|
-
'templateUrl' => url("/?u=#{Rack::Utils.escape(meme_data.meme_id)}"),
|
209
|
-
}.to_json]
|
210
|
-
rescue => error
|
211
|
-
logger.error "error generating image: #{error.class} #{error.message}"
|
212
|
-
logger.error(MemeCaptain.pretty_format(error.backtrace))
|
213
|
-
[500, { 'Content-Type' => 'text/plain' }, 'Error generating image']
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def serve_img(meme_data)
|
218
|
-
meme_data.requested!
|
219
|
-
|
220
|
-
if meme_data.respond_to?(:texts)
|
221
|
-
meme_text = meme_data.texts.map do |text|
|
222
|
-
Rack::Utils.escape(text['text'])
|
223
|
-
end.join('&')
|
224
|
-
|
225
|
-
headers 'Meme-Text' => meme_text
|
226
|
-
end
|
227
|
-
|
228
|
-
send_file meme_data.fs_path, :type => meme_data.mime_type
|
229
|
-
end
|
230
|
-
|
231
|
-
get '/i' do
|
232
|
-
raise Sinatra::NotFound if params[:u].to_s.empty?
|
233
|
-
|
234
|
-
serve_img(gen(params))
|
235
|
-
end
|
236
|
-
|
237
|
-
get %r{^/([a-f0-9]+\.(?:gif|jpg|png))$} do
|
238
|
-
if meme_data = MemeData.find_by_meme_id(params[:captures][0])
|
239
|
-
serve_img meme_data
|
240
|
-
else
|
241
|
-
raise Sinatra::NotFound
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
post '/upload' do
|
246
|
-
redirect('/') unless params[:upload]
|
247
|
-
|
248
|
-
img = ImageList::SourceImage.new
|
249
|
-
img.from_blob(params[:upload][:tempfile].read)
|
250
|
-
img.prepare! settings.source_img_max_side, settings.watermark
|
251
|
-
fs_path = img.cache(params[:upload][:filename], 'source_cache')
|
252
|
-
|
253
|
-
filename_hash = Digest::SHA1.hexdigest(params[:upload][:filename])
|
254
|
-
|
255
|
-
len = 6
|
256
|
-
upload_id = filename_hash[0,len]
|
257
|
-
while Upload.where(:upload_id => upload_id).count > 0
|
258
|
-
upload_id = if len < filename_hash.size
|
259
|
-
len += 1
|
260
|
-
filename_hash[0,len]
|
261
|
-
else
|
262
|
-
"#{upload_id}0"
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
upload = Upload.new(
|
267
|
-
:upload_id => upload_id,
|
268
|
-
:fs_path => fs_path,
|
269
|
-
:mime_type => img.mime_type,
|
270
|
-
:size => File.size(fs_path),
|
271
|
-
:request_count => 0,
|
272
|
-
:creator_ip => request.ip
|
273
|
-
)
|
274
|
-
|
275
|
-
img.each { |frame| frame.destroy! }
|
276
|
-
|
277
|
-
upload.save! :safe => true
|
278
|
-
|
279
|
-
redirect "/?u=#{settings.upload_prefix}#{Rack::Utils.escape(upload_id)}"
|
280
|
-
end
|
281
|
-
|
282
|
-
get %r{/#{settings.upload_prefix}(.+)} do
|
283
|
-
if upload = Upload.find_by_upload_id(params[:captures][0])
|
284
|
-
serve_img upload
|
285
|
-
else
|
286
|
-
raise Sinatra::NotFound
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
not_found do
|
291
|
-
@root_url = url('/')
|
292
|
-
|
293
|
-
erb :'404'
|
294
|
-
end
|
295
|
-
|
296
|
-
helpers do
|
297
|
-
include Rack::Utils
|
298
|
-
alias_method :h, :escape_html
|
299
|
-
end
|
300
|
-
|
301
|
-
end
|
302
|
-
|
303
|
-
end
|