memebot/memes.lua

806 lines
28 KiB
Lua

local memes = {}
local internet = require 'internet'
local imlib = require 'imlib2'
local CONFIG = require 'config'
--------------------------------------------------------------------------------
-- Util
local function reverse (l0)
local l, j = {}, #l0
for i = 1, #l0 do
l[i], j = l0[j], j - 1
end
return l
end
local function choose(l)
assert(type(l) == 'table')
return l[math.random(#l)]
end
local function shallow_copy (t0)
local t = {}
for k,v in pairs(t0) do t[k] = v end
return t
end
local function clean_text (text)
return text:gsub('%s+', ' '):match('^%s*(.-)%s*$')
end
local function check_file_exists (filename)
assert(type(filename) == 'string')
local status = os.execute('test -e "'..filename..'"')
return status == 0
end
--------------------------------------------------------------------------------
-- Internet shit
local function copy_remotely (origin_server, origin_path, target_server, target_path)
local local_only = (origin_server == 'localhost' and target_server == 'localhost')
local origin = origin_server and origin_server ~= 'localhost' and origin_server..':'..origin_path or origin_path
local target = target_server and target_server ~= 'localhost' and target_server..':'..target_path or target_path
local cmd = local_only and 'cp' or 'scp'
--
if origin_server == 'localhost' and not check_file_exists(origin_path) then
error('File "'..origin_path..'" does not exist!')
end
--
local status = os.execute(cmd..' '..origin..' '..target)
if status ~= 0 then
error('Could not copy file! Got error code: '..tostring(status))
end
end
local function save_file_to_dcav (filename, ext)
assert(type(filename) == 'string')
-- Upload to dcav
local ext = ext or filename:match '%.(%a+)$'
local remote_name = 'otmemes_'..os.time()..'.'..ext
copy_remotely('localhost', filename, CONFIG.STORAGE_SERVER, CONFIG.STORAGE_SERVER_PATH..remote_name)
return CONFIG.STORAGE_DIR_URL..remote_name
end
memes.save_file_to_dcav = save_file_to_dcav
local function save_img (img)
assert(img)
-- Set format if not yet set
if img:get_format() == nil then
img:set_format 'png'
end
--
local filename = os.tmpname() .. '.' .. img:get_format()
img:save(filename)
img:free()
return filename
end
local function save_img_to_cloud (img)
assert(img)
--
local filename = save_img(img)
return save_file_to_dcav(filename)
end
--------------------------------------------------------------------------------
-- Draw shit
local function flatten_onto(target_img, other_img, x0, y0)
assert(x0 + other_img:get_width() <= target_img:get_width())
assert(y0 + other_img:get_height() <= target_img:get_height())
for x = 0, other_img:get_width() do
for y = 0, other_img:get_height() do
target_img:draw_pixel(x + x0, y + y0, other_img:get_pixel(x, y))
end
end
--
return
end
local MAX_FONT_SIZE = 1000
local function fit_font_to_line_height (font_name, height)
assert(type(font_name) == 'string')
assert(type(height) == 'number')
--
local size_min, size_max = 1, MAX_FONT_SIZE
while true do
local size_guess = math.floor((size_max + size_min)/2)
assert(size_min <= size_guess and size_guess <= size_max)
local font = assert(imlib.font.load(font_name..'/'..size_guess))
if size_guess == size_min then return font, size_guess end
local text_w, text_h = font:get_size 'k'
--
if text_h <= height then size_min = size_guess
else size_max = size_guess
end
end
return nil
end
local function load_font_of_size (font_name, size)
return assert(imlib.font.load(font_name..'/'..size))
end
local function determine_required_font_size (font_name, text, width)
assert(type(font_name) == 'string')
assert(type(text) == 'string')
assert(type(width) == 'number')
--
local size_min, size_max = 1, MAX_FONT_SIZE
while true do
local size_guess = math.floor((size_max + size_min)/2)
assert(size_min <= size_guess and size_guess <= size_max)
local font = load_font_of_size(font_name, size_guess)
if size_guess == size_min then return font, size_guess end
local text_w, text_h = font:get_size(text)
--
if text_w <= width then size_min = size_guess
else size_max = size_guess
end
end
return nil
end
local function wrap_lines (font, text, width)
local lines, current, x = {}, {}, 0
local SPACE_ADVANCE = font:get_advance ' '
for word in text:gmatch '[^%s]+' do
assert(type(word) == 'string')
local word_w = font:get_advance(word)
local next_x = x + word_w + SPACE_ADVANCE
if word == '' then
-- Do nothing
elseif next_x <= width then
current[#current+1], x = word, next_x
else
lines[#lines+1], current = table.concat(current, ' '), { word }
x = word_w
end
end
-- Færdiggør sidste linje
lines[#lines+1] = table.concat(current, ' ')
-- Ret
return lines
end
local COLOR_WHITE = imlib.color.new(255, 255, 255)
local COLOR_BLACK = imlib.color.new( 0, 0, 0)
local function draw_centered_lines (draw_onto, lines, x0, y0, width, font, font_colors)
assert(type(lines) == 'table')
assert(type(font_colors) == 'table' and #font_colors >= 1)
--
local y = y0
for i, line in ipairs(lines) do
local text_w, text_h = font:get_size(line)
local SHADOW_OFFSET = select(2, font:get_size(line)) / -20
local x = x0 + (width - text_w) / 2
for i, color in ipairs(type(font_colors) == 'table' and font_colors or {font_colors}) do
local offset = (i-1) * SHADOW_OFFSET
draw_onto:draw_text(font, line, x + offset, y + offset, color)
end
--
y = y + text_h
end
end
local function determine_font_and_lines_for_box (font_name, text, width, height)
local num_lines, last_actual, actual_lines = 1, nil, nil
for iteration = 1, 100 do
local estimate_font = determine_required_font_size(font_name, text, width * num_lines)
local line_height = select(2, estimate_font:get_size(text))
local estimate_num_lines = height / select(2, estimate_font:get_size(text))
local lines = wrap_lines(estimate_font, text, width)
local actual_num_lines = #lines
if #lines * line_height >= height then
estimate_num_lines = estimate_num_lines - 1
end
-- Test for convergence
if last_actual == actual_num_lines then
actual_lines = lines
break
end
num_lines = (estimate_num_lines + actual_num_lines) / 2
last_actual = actual_num_lines
end
assert(actual_lines)
-- Find final font size
local _, min_font_size = fit_font_to_line_height(font_name, height / #actual_lines)
for _, line in ipairs(actual_lines) do
min_font_size = math.min(min_font_size, select(2, determine_required_font_size(font_name, line, width)))
end
local actual_font = load_font_of_size(font_name, min_font_size)
-- Assertions and error correction
--[[
if (#actual_lines * select(2, actual_font:get_size(text)) < height) then
io.write(' !! Performed bad fitting of text: '..text..'\n')
actual_font, actual_lines = determine_required_font_size(font_name, text, width), {text}
end
--]]
return actual_font, actual_lines
end
local function draw_centered_text_in_box (font_name, draw_onto, text, x0, y0, width, height, bg_color, font_colors)
assert(type(font_name) == 'string')
assert(type(font_colors) == 'table' and #font_colors >= 1)
--
local font, lines = determine_font_and_lines_for_box(font_name, text, width, height)
--
local y = y0 + (height - #lines * select(2, font:get_size(text))) / 2
--
if bg_color then draw_onto:fill_rectangle(x0, y0, width, height, bg_color) end
draw_centered_lines(draw_onto, lines, x0, y, width, font, font_colors)
end
local function choose_random_font ()
local fonts = imlib.font.list_fonts()
assert(#fonts > 0, 'Could not find any fonts')
return fonts[math.random(#fonts)]
end
local function load_random_font ()
local font_name = choose_random_font()
local font, errmsg = imlib.font.load(font_name..'/30')
assert(font, errmsg)
return font_name
end
local function paste_topic_onto_image (target, topic, x, y, w, h, bg_color, font_name, font_color)
assert(target)
assert(type(topic) == 'table')
assert(type(font_name) == 'string')
if not font_color then font_color = { COLOR_BLACK } end
assert(type(font_color) == 'table' and #font_color >= 1)
-- Download and paste found image
if topic.type == 'image' then
assert(type(topic.filename) == 'string')
assert(not topic.url)
local found_img = assert(imlib.image.load(topic.filename))
found_img:crop_and_scale(0, 0, found_img:get_width(), found_img:get_height(), w, h)
flatten_onto (target, found_img, x, y)
found_img:free()
--os.remove(filename)
elseif topic.type == 'text' then
assert(type(topic.text) == 'string')
local text = topic.text
draw_centered_text_in_box(font_name, target, text, x, y, w, h, bg_color, font_color)
elseif topic.type == 'droste' then
target:fill_rectangle(x, y, w, h, COLOR_WHITE)
else
assert(false, topic.type)
end
end
local DROSTE_ITERATIONS_DEFAULT = 10
local function draw_droste_effect (target_image, droste_positions, iterations)
assert(type(droste_positions) == 'table')
iterations = interations or DROSTE_ITERATIONS_DEFAULT
assert(type(iterations) == 'number')
--
if #droste_positions <= 0 or iterations <= 0 then return target_image end
for _ = 1, iterations do
for _, position in ipairs(droste_positions) do
local paste_image = target_image:clone()
paste_image:crop_and_scale(0, 0, paste_image:get_width(), paste_image:get_height(), position.w, position.h)
flatten_onto (target_image, paste_image, position.x, position.y)
paste_image:free()
end
end
return target_image
end
--------------------------------------------------------------------------------
-- Meme modifiers
local function add_compression_artifacts_to_image (image_filename, quality)
-- Recommend quality < 10. Repeat runs at very low quality will
-- not further destroy the image.
assert(type(image_filename) == 'string')
assert(type(quality) == 'number' and quality == math.floor(quality) and quality > 0 and quality < 100)
--
local output_filename = os.tmpname()..'.jpg'
local img = imlib.image.load(image_filename)
img:save(output_filename)
img:free()
-- Mogrify to low quality
os.execute('mogrify -quality '..quality..' "'..output_filename..'"')
--
return output_filename
end
local function add_banner_to_image (image_filename, banner_filename, x_offset, background_color)
assert(type(image_filename) == 'string')
assert(type(banner_filename) == 'string')
assert(type(x_offset) == 'number')
--
local image_img = assert(imlib.image.load(image_filename))
local banner_img = assert(imlib.image.load(banner_filename))
local combi_img = imlib.image.new( image_img:get_width(), image_img:get_height() + banner_img:get_height() )
local xpos = (0 <= x_offset) and x_offset or (combi_img:get_width() - banner_img:get_width() + x_offset)
-- Draw
if background_color then
combi_img:draw_rectangle(0, 0, combi_img:get_width(), combi_img:get_height(), background_color)
end
flatten_onto(combi_img, image_img, 0, 0)
flatten_onto(combi_img, banner_img, xpos, image_img:get_height())
-- Save and free
image_img:free()
banner_img:free()
local output_filename = os.tmpname()..'.jpg'
combi_img:save(output_filename)
combi_img:free()
return output_filename
end
local CHANCE_OF_MODIFIER = 0.3
local modifiers = {
-- Compression artifacts
function (image_filename) return add_compression_artifacts_to_image(image_filename, math.random(1, 20)) end,
-- iFunny banner
function (image_filename) return add_banner_to_image(image_filename, 'images/banner_ifunny.png', -7, imlib.color.new(27, 27, 27)) end,
}
--------------------------------------------------------------------------------
-- Comparison memes
local DROSTE_EFFECT_TRIGGERS = {
['induktion'] = true,
['rekursion'] = true,
['uendelig rekursion'] = true,
['rekursive'] = true,
['rekursive funktioner'] = true,
['recursion'] = true,
['infinite recursion'] = true,
['tail recursion'] = true,
['recursive'] = true,
['recursive function'] = true,
['induktion'] = true,
['droste'] = true,
['drostle'] = true, -- Misspelling
['uendelig'] = true,
['uendeligt'] = true,
['strange loop'] = true,
['loop'] = true,
}
local function download_and_standardize_image (image_url)
local file_extension = image_url:match '%.(%a+)$'
local url, filename = image_url, os.tmpname()
assert(type(url) == 'string' and #url > 0)
assert(type(filename) == 'string' and #filename > 0)
local success, errmsg = internet.download_file(url, filename)
-- Convert svg to png
if success and url:match '%.svg$' then
local filename_2 = filename..'.svg'
os.execute('convert -density "1200" -resize 400x400 "'..filename..'" "'..filename_2..'" &> /dev/null')
filename = filename_2
assert(check_file_exists(filename_2))
end
--
return success and filename, errmsg
end
local function fill_in_topics_information (topics)
assert(type(topics) == 'table')
--
local topic_to_image_url = internet.search_images(topics)
--
local new_topics = {}
for i, topic in ipairs(topics) do
assert(type(topic) == 'string')
local url = topic_to_image_url[topic]
if DROSTE_EFFECT_TRIGGERS[topic] then
new_topics[i] = { topic = topic, type = 'droste' }
elseif url then
local filename = download_and_standardize_image(url)
new_topics[i] = { topic = topic, type = 'image', filename = filename }
else
new_topics[i] = { topic = topic, type = 'text', text = topic }
end
end
return new_topics
end
local function droste_positions_from_topics (topics, places)
local droste_poss = {}
for i, topic in ipairs(topics) do
if topic.type == 'droste' then
droste_poss[#droste_poss+1] = {
x = places[i].x, y = places[i].y,
w = places[i].w, h = places[i].h,
}
end
end
return droste_poss
end
local function generate_comparison_meme_generator (positions)
assert(type(positions) == 'table')
assert(type(positions.base_img_path) == 'string')
return function (topics)
assert(type(topics) == 'table' and #topics == #positions)
local font_name = choose_random_font()
local base_img = assert(imlib.image.load(positions.base_img_path))
-- Randomize pos
local rand_positions = {}
for i, pos in ipairs(positions) do
rand_positions[i] = shallow_copy(pos)
rand_positions[i].x = pos.x + math.random(-(pos.xr or 0), pos.xr or 0)
rand_positions[i].y = pos.y + math.random(-(pos.yr or 0), pos.yr or 0)
end
-- Paste topic onto head
for index, pos in ipairs(rand_positions) do
-- Font colors
if pos.font_color == nil then pos.font_color = COLOR_BLACK end
local font_colors = {}
if pos.font_color == COLOR_WHITE then font_colors[1] = COLOR_BLACK
elseif pos.font_color == COLOR_BLACK then font_colors[1] = COLOR_WHITE
end
table.insert(font_colors, pos.font_color)
-- Paste
assert(base_img, topics[index])
assert(type(font_colors) == 'table' and #font_colors >= 1)
paste_topic_onto_image(base_img, topics[index], pos.x, pos.y, pos.w, pos.h, nil, font_name, font_colors)
end
-- Droste
base_img = draw_droste_effect(base_img, droste_positions_from_topics(topics, rand_positions))
-- Save img
local image_filename = save_img(base_img)
-- Use modifiers
while math.random() < CHANCE_OF_MODIFIER do
image_filename = choose(modifiers)(image_filename)
end
return save_file_to_dcav(image_filename)
end
end
local generate_distracted_boyfriend = generate_comparison_meme_generator {
base_img_path = './images/distracted_boyfriend.jpg',
{ x = 640, xr = 20, y = 50, yr = 20, w = 150, h = 150 },
{ x = 180, xr = 20, y = 50, yr = 20, w = 150, h = 150 },
}
local generate_distracted_boyfriend_oldy_times = generate_comparison_meme_generator {
base_img_path = './images/distracted_boyfriend_oldy_times.jpg',
{ x = 650, xr = 10, y = 100, yr = 20, w = 150, h = 150, font_color = COLOR_WHITE },
{ x = 124, xr = 10, y = 38, yr = 10, w = 250, h = 250, font_color = COLOR_WHITE },
}
local generate_drake_egon_olsen = generate_comparison_meme_generator {
base_img_path = './images/drake_egon.png',
{ x = 380, xr = 0, y = 0, yr = 0, w = 380, h = 354 },
{ x = 377, xr = 0, y = 354, yr = 0, w = 383, h = 360 },
}
local generate_skorsten_image = generate_comparison_meme_generator {
base_img_path = './images/bamse_skorsten_1.png',
{ x = 646, xr = 0, y = 366, yr = 0, w = 631, h = 215, font_color = COLOR_WHITE },
}
local generate_into_the_trash = generate_comparison_meme_generator {
base_img_path = './images/into_the_trash.png',
{ x = 377, xr = 20, y = 261, yr = 20, w = 400, h = 400, font_color = COLOR_BLACK },
}
local generate_is_this_a_pidgeon = generate_comparison_meme_generator {
base_img_path = './images/is_this_a_pidgeon.png',
{ x = 1100, xr = 20, y = 100, yr = 20, w = 450, h = 450, font_color = COLOR_WHITE },
{ x = 15, xr = 0, y = 1200, yr = 0, w = 1587 - 15, h = 1443-1200-15, font_color = COLOR_WHITE },
}
local generate_omg_his_first_word do
local internal = generate_comparison_meme_generator {
base_img_path = './images/his_first_words.png',
{ x = 20, xr = 0, y = 10, yr = 0, w = 325, h = 83, font_color = COLOR_BLACK, type = 'text' },
{ x = 371, xr = 0, y = 10, yr = 0, w = 316, h = 100, font_color = COLOR_BLACK, type = 'text' },
{ x = 29, xr = 0, y = 374, yr = 0, w = 455, h = 155, font_color = COLOR_BLACK, type = 'text' },
}
generate_omg_his_first_word = function (text)
assert(type(text) == 'string')
local short = text:sub(1,1)..'...'..text:sub(1,2)..'...'
return internal {
{ type = 'text', text = short },
{ type = 'text', text = 'Åh gud! Hans første ord!' },
{ type = 'text', text = text }
}
end
end
local GENERATE_COMPARISON_MEME_OF_2 = {
generate_distracted_boyfriend,
generate_distracted_boyfriend_oldy_times,
generate_drake_egon_olsen
}
local BRAIN_ROW_HEIGHT = 150
local BRAIN_ROW_WIDTH = 200
local BRAIN_MAX_EXPLOSION_TOPICS = 6
local BRAIN_DROSTE_POS = {}
for i = 1, BRAIN_MAX_EXPLOSION_TOPICS do
BRAIN_DROSTE_POS[i] = {
x = 0,
y = (i-1) * BRAIN_ROW_HEIGHT,
w = BRAIN_ROW_WIDTH,
h = BRAIN_ROW_HEIGHT
}
end
local function generate_brain_explosion_image (topics)
assert(type(topics) == 'table' and 1 <= #topics and #topics <= BRAIN_MAX_EXPLOSION_TOPICS)
--
local base_img = imlib.image.new(BRAIN_ROW_WIDTH * 2, BRAIN_ROW_HEIGHT * #topics)
base_img:fill_rectangle(0, 0, BRAIN_ROW_WIDTH * 2, BRAIN_ROW_HEIGHT * #topics, COLOR_WHITE)
local font_name = choose_random_font()
--
for i, topic_info in ipairs(topics) do
paste_topic_onto_image(base_img, topic_info, 0, (i-1) * BRAIN_ROW_HEIGHT, BRAIN_ROW_WIDTH, BRAIN_ROW_HEIGHT, COLOR_WHITE, font_name)
local brain_path = CONFIG.IMGGEN_PATH_BRAINS..'brain_'..i..'.png'
local brain_img = imlib.image.load(brain_path)
if brain_img then
brain_img:crop_and_scale(0, 0, brain_img:get_width(), brain_img:get_height(), BRAIN_ROW_WIDTH, BRAIN_ROW_HEIGHT)
flatten_onto (base_img, brain_img, BRAIN_ROW_WIDTH, (i-1) * BRAIN_ROW_HEIGHT)
brain_img:free()
else
io.stderr:write ('[ERROR]: Could not find brain image "'..brain_path..'"\n')
assert(false)
end
end
-- Droste
base_img = draw_droste_effect(base_img, droste_positions_from_topics(topics, BRAIN_DROSTE_POS))
-- Save
return save_img_to_cloud(base_img)
end
local function is_comparison_message (message)
local leq, gep = message:match '<', message:match '>'
return leq and not gep and '<' or not leq and gep and '>'
end
local COMP_SENTENCES do
local ORD_MED_ATTITYDE = {
bedre = 'positiv',
dårligere = 'negativ',
hurtigere = 'positiv',
langsommere = 'negativt',
robust = 'positivt',
}
COMP_SENTENCES = {}
for ord, attityde in pairs(ORD_MED_ATTITYDE) do
local first, second = '{A}', '{B}'
if attityde == 'negativ' then first, second = second, first end
for _, fmt in ipairs { '%s er %s end %s', '%s er mere %s end %s', '%s er meget %s end %s', '%s %s end %s' } do
table.insert(COMP_SENTENCES, fmt:format(first, ord, second))
end
end
end
for sentence_i, sentence in ipairs(COMP_SENTENCES) do
local A_pos, B_pos = sentence:find '{A}', sentence:find '{B}'
local best_first = (A_pos < B_pos)
local pattern_sentence = sentence:gsub('{[AB]}', '(.+)'):gsub('%s+','%%s+')
COMP_SENTENCES[pattern_sentence] = { best_first = best_first }
COMP_SENTENCES[sentence_i] = nil
end
local function get_topics_from_comparison_message(message)
local comp = is_comparison_message(message)
if comp then
local topics = {}
for topic in message:gmatch('[^'..comp..']+') do
local topic_text = clean_text(topic)
if topic_text:match '[^%s]' then
topics[#topics+1] = topic_text
end
end
-- Rev
if comp == '>' then topics = reverse(topics) end
--
return (#topics >= 2) and topics or nil
end
-- Natural language comparisons
for pattern, sentence_info in pairs(COMP_SENTENCES) do
local good, bad = message:lower():match(pattern)
if not sentence_info.best_first then good, bad = bad, good end
if good then return { bad, good } end
end
--
return nil
end
--------------------------------------------------------------------------------
-- Other memes
local function generate_bait_link()
return 'https://dcav.pw/jbait'
end
local curb = require 'curb_your_enthusiasm'
--------------------------------------------------------------------------------
local function is_image_link (str)
if str:match '%.png$' or str:match '%.gif$' or str:match '%.jpg$' then
return true
end
--
if type(str) ~= 'string' then return false end
if not str:match '^%a+://.+$' then return false end
local headers = internet.download_headers(str)
return type(headers) == 'table' and headers['content-type']:match '^image/%a+$'
end
function memes.generate_for_message (user, message)
-- Bait msg
if message:match '%f[%a]bait%f[%A]' then
return generate_bait_link(), 'BAIT'
end
-- Meme machine
if message:match '%f[%a]meme%s+machine%f[%A]' then
return 'https://www.youtube.com/watch?v=wl-LeTFM8zo', 'MACHINE'
end
do -- Curb your enthusiasm
local url = message:match '^[Cc]urb%s+[Yy]our%s+(.+)$'
if url then
local url2, timestamp = message:match '^(..-)%s+at%s+(-?[%d.]+)$'
if url2 then url = url2 end
timestamp = timestamp and tonumber(timestamp) or nil
assert(type(timestamp) == 'number' or timestamp == nil)
local video_filename = curb.your_video(url, timestamp)
assert(check_file_exists(video_filename))
local video_url = save_file_to_dcav(video_filename)
os.remove(video_filename)
return video_url, 'CURB'
end
end
-- Vælter min skorsten
do
local problem_text = message:lower():match 'vælter%s+min%s+skorsten%s*(.+)$'
if problem_text then
if problem_text:match '^er' then problem_text = problem_text:match '^er%s*(.+)$' end
if problem_text:match '^:' then problem_text = problem_text:match '^:%s*(.+)$' end
local img_link = generate_skorsten_image {{ type = 'text', text = problem_text }}
return img_link, 'SKRSTEN'
end
end
-- Into the trash
do
-- Attempt to match
local problem_text
for _, pattern in ipairs { '^(.-)%s+[Ee][Rr]%s+[Ss][Kk][Rr][Aa][Ll][Dd](.-)$', '^(.-)%s+[Ii][Ss]%s+[Tt][Rr][Aa][Ss][Hh](.-)$' } do
problem_text = message:match(pattern)
if problem_text then break end
end
-- Create image based on match
if problem_text then
local topic = fill_in_topics_information { problem_text }
local img_link = generate_into_the_trash(topic)
return img_link, 'TRASH'
end
end
-- Is this a rich picture?
if is_image_link(message) then
local filename, status = download_and_standardize_image(message)
if filename then
local img_link = generate_is_this_a_pidgeon {
{ type = 'image', filename = filename },
{ type = 'text', text = 'Is this a rich picture?' }
}
return img_link, 'KYNG'
else
img_link = 'Kunne ikke skaffe det billede. Fik fejlkode '..tostring(status)
return img_link, '!KYNG'
end
end
-- OMG his first word
if math.random() < 0.01 then
local img_link = generate_omg_his_first_word(message)
return img_link, 'OMG'
end
-- Comparison memes
local topics = get_topics_from_comparison_message(message)
if not topics then return end
local topics = fill_in_topics_information(topics)
--
assert(#topics >= 2)
local img_link = (#topics == 2) and choose(GENERATE_COMPARISON_MEME_OF_2)(topics)
or generate_brain_explosion_image(topics)
--
return img_link, 'COMPAR'
end
--------------------------------------------------------------------------------
-- Find memes from dankmark
local DANKMARK_MIN_SCORE = 60
function memes.generate_meme_report (subreddits, time_interval)
assert(type(subreddits) == 'table' and #subreddits == 1)
assert(type(time_interval) == 'table' and #time_interval == 2)
local current_check_time = os.time()
local new_memes = internet.find_reddit_memes(subreddits[1], function(t) return DANKMARK_MIN_SCORE <= t.score and time_interval[1] < t.created and t.created <= time_interval[2] end)
if #new_memes == 0 then return end
-- Find best meme
local best_meme = new_memes[1]
for i = 2, #new_memes do
if best_meme.score < new_memes[i].score then best_meme = new_memes[i] end
end
-- Return message to IRC
return string.format('%s: %s', best_meme.title, best_meme.url)
end
--------------------------------------------------------------------------------
return memes