Class: Meme

Inherits:
Object
  • Object
show all
Defined in:
lib/meme.rb

Overview

Generate memes using memegenerator.net

Defined Under Namespace

Classes: Error

Constant Summary collapse

VERSION =

Every meme generator needs a version

'1.9'
USER_AGENT =

For statistics!

"meme/#{VERSION} Ruby/#{RUBY_VERSION}"
GENERATORS =

We have some generators up-in-here

Hash.new do |_, k|
  raise Error, "unknown generator #{k}"
end

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(generator) ⇒ Meme

Generates links for generator



152
153
154
# File 'lib/meme.rb', line 152

def initialize generator
  @template_id, @template_type, @generator_name, @default_line = GENERATORS.match generator
end

Class Method Details

.advice_dog(name, id, template_name, first_line = nil) ⇒ Object

For creating advice-dog type meme images.

These can accept up to two lines of text



38
39
40
41
42
43
# File 'lib/meme.rb', line 38

def self.advice_dog name, id, template_name, first_line = nil
  template = [id, 'AdviceDogSpinoff', template_name, first_line]
  template.compact

  GENERATORS[name] = template
end

.run(argv = ARGV) ⇒ Object

Interface for the executable



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/meme.rb', line 115

def self.run argv = ARGV
  generator = ARGV.shift

  if generator == '--list' then
    width = GENERATORS.keys.map { |command| command.length }.max

    GENERATORS.sort.each do |command, (id, name, _)|
      puts "%-*s  %s" % [width, command, name]
    end

    exit
  end

  abort "#{$0} [GENERATOR|--list] LINE [ADDITONAL_LINES]" if ARGV.empty?

  meme = new generator
  link = meme.generate *ARGV

  meme.paste link

  if $stdout.tty?
    puts link
  else
    puts meme.fetch link
  end
  link
rescue Interrupt
  exit
rescue SystemExit
  raise
rescue Exception => e
  abort "ERROR: #{e.message} (#{e.class})"
end

.vertical(name, id, template_name) ⇒ Object

For creating vertical type meme images

These can accept multiple lines of text



50
51
52
# File 'lib/meme.rb', line 50

def self.vertical name, id, template_name
  GENERATORS[name] = [id, 'Vertical', template_name]
end

Instance Method Details

#fetch(link) ⇒ Object



199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/meme.rb', line 199

def fetch link
  url = URI.parse link
  res = nil

  Net::HTTP.start url.host do |http|
    get = Net::HTTP::Get.new url.request_uri
    get['User-Agent'] = USER_AGENT

    res = http.request get
  end
  res.body
end

#generate(*args) ⇒ Object

Generates a meme with line1 and line2. For some generators you only have to supply one line because the first line is defaulted for you. Isn’t that great?

Raises:



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/meme.rb', line 161

def generate *args
  url = URI.parse 'http://memegenerator.net/Instance/CreateOrEdit'
  res = nil
  location = nil

  # Prepend the default line if this meme has one and we only had 1 text input
  args.unshift @default_line if @default_line and args.size <= 1

  raise Error, "two lines are required for #{@generator_name}" unless
    args.size > 1

  post_data = { 'templateType'  => @template_type,
                'templateID'    => @template_id,
                'generatorName' => @generator_name }

  # go through each argument and add it back into the post data as textN
  (0..args.size).map {|num| post_data.merge! "text#{num}" => args[num] }

  Net::HTTP.start url.host do |http|
    post = Net::HTTP::Post.new url.path
    post['User-Agent'] = USER_AGENT
    post.set_form_data post_data

    res = http.request post

    location = res['Location']
    redirect = url + location

    get = Net::HTTP::Get.new redirect.request_uri
    get['User-Agent'] = USER_AGENT

    res = http.request get
  end

  doc = Nokogiri.HTML res.body
  doc.css("a[href=\"#{location}\"] img").first['src']
end

#paste(link) ⇒ Object

Tries to find clipboard copy executable and if found puts link in your clipboard.



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/meme.rb', line 216

def paste link
  require 'pasteboard'

  clipboard = Pasteboard.new

  jpeg = fetch link

  clipboard.put_jpeg_url jpeg, link
rescue LoadError
  clipboard = %w{
    /usr/bin/pbcopy
    /usr/bin/xclip
  }.find { |path| File.exist? path }

  if clipboard
    IO.popen clipboard, 'w' do |io| io.write link end
  end
end