├── api
├── public
│ ├── m
│ │ └── .gitignore
│ └── img
│ │ ├── fry.png
│ │ ├── aliens.jpg
│ │ ├── kenobi.gif
│ │ ├── kenobi.jpg
│ │ ├── mugatu.jpg
│ │ ├── sparta.jpg
│ │ ├── taken.jpg
│ │ ├── walter.jpg
│ │ ├── wonka.jpg
│ │ ├── xzibit.jpg
│ │ ├── y_u_no.jpg
│ │ ├── boromir.jpg
│ │ ├── emperor.jpg
│ │ ├── ned_stark.jpg
│ │ ├── over_9000.jpg
│ │ ├── batman-slap.jpg
│ │ ├── craig-happy.jpg
│ │ ├── inquisition.jpg
│ │ ├── all_the_things.jpg
│ │ ├── goes_to_eleven.jpg
│ │ ├── i_am_the_law.jpg
│ │ ├── kermit-panic.gif
│ │ ├── laughing-men.jpg
│ │ ├── too_damn_high.jpg
│ │ ├── conspiracy_keanu.jpg
│ │ ├── fantastic-doctor.jpg
│ │ ├── most_interesting.jpg
│ │ ├── shampoo-is-better.jpg
│ │ └── you_should_feel_bad.jpg
├── .gitignore
├── Impact.ttf
├── test
│ ├── init.rb
│ └── regex_spec.rb
├── config.template.yml
├── Rakefile
├── config.ru
├── Gemfile
├── schema.sql
├── README.md
├── Gemfile.lock
├── lib
│ └── meme-match.rb
├── memes.json
└── app.rb
├── .travis.yml
└── README.md
/api/public/m/.gitignore:
--------------------------------------------------------------------------------
1 | *.jpg
2 | *.gif
3 |
--------------------------------------------------------------------------------
/api/.gitignore:
--------------------------------------------------------------------------------
1 | config.yml
2 | .DS_Store
3 | .bundle/
4 | vendor/
--------------------------------------------------------------------------------
/api/Impact.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/Impact.ttf
--------------------------------------------------------------------------------
/api/public/img/fry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/fry.png
--------------------------------------------------------------------------------
/api/public/img/aliens.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/aliens.jpg
--------------------------------------------------------------------------------
/api/public/img/kenobi.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/kenobi.gif
--------------------------------------------------------------------------------
/api/public/img/kenobi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/kenobi.jpg
--------------------------------------------------------------------------------
/api/public/img/mugatu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/mugatu.jpg
--------------------------------------------------------------------------------
/api/public/img/sparta.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/sparta.jpg
--------------------------------------------------------------------------------
/api/public/img/taken.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/taken.jpg
--------------------------------------------------------------------------------
/api/public/img/walter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/walter.jpg
--------------------------------------------------------------------------------
/api/public/img/wonka.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/wonka.jpg
--------------------------------------------------------------------------------
/api/public/img/xzibit.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/xzibit.jpg
--------------------------------------------------------------------------------
/api/public/img/y_u_no.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/y_u_no.jpg
--------------------------------------------------------------------------------
/api/test/init.rb:
--------------------------------------------------------------------------------
1 | require 'minitest/autorun'
2 | require 'json'
3 | require './lib/meme-match'
4 |
5 |
--------------------------------------------------------------------------------
/api/public/img/boromir.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/boromir.jpg
--------------------------------------------------------------------------------
/api/public/img/emperor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/emperor.jpg
--------------------------------------------------------------------------------
/api/public/img/ned_stark.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/ned_stark.jpg
--------------------------------------------------------------------------------
/api/public/img/over_9000.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/over_9000.jpg
--------------------------------------------------------------------------------
/api/public/img/batman-slap.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/batman-slap.jpg
--------------------------------------------------------------------------------
/api/public/img/craig-happy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/craig-happy.jpg
--------------------------------------------------------------------------------
/api/public/img/inquisition.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/inquisition.jpg
--------------------------------------------------------------------------------
/api/public/img/all_the_things.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/all_the_things.jpg
--------------------------------------------------------------------------------
/api/public/img/goes_to_eleven.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/goes_to_eleven.jpg
--------------------------------------------------------------------------------
/api/public/img/i_am_the_law.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/i_am_the_law.jpg
--------------------------------------------------------------------------------
/api/public/img/kermit-panic.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/kermit-panic.gif
--------------------------------------------------------------------------------
/api/public/img/laughing-men.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/laughing-men.jpg
--------------------------------------------------------------------------------
/api/public/img/too_damn_high.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/too_damn_high.jpg
--------------------------------------------------------------------------------
/api/public/img/conspiracy_keanu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/conspiracy_keanu.jpg
--------------------------------------------------------------------------------
/api/public/img/fantastic-doctor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/fantastic-doctor.jpg
--------------------------------------------------------------------------------
/api/public/img/most_interesting.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/most_interesting.jpg
--------------------------------------------------------------------------------
/api/public/img/shampoo-is-better.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/shampoo-is-better.jpg
--------------------------------------------------------------------------------
/api/public/img/you_should_feel_bad.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aaronpk/Meme-API/main/api/public/img/you_should_feel_bad.jpg
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.6.3
4 | root: false
5 | gemfile: api/Gemfile
6 | script: sh -c 'cd api && bundle exec rake'
7 |
--------------------------------------------------------------------------------
/api/config.template.yml:
--------------------------------------------------------------------------------
1 | base_url: http://localhost:9393
2 | google_server_key:
3 | google_cx:
4 | database: "mysql2://root@127.0.0.1/memes"
5 |
--------------------------------------------------------------------------------
/api/Rakefile:
--------------------------------------------------------------------------------
1 | Bundler.require
2 | require 'rake/testtask'
3 |
4 | Rake::TestTask.new do |t|
5 | t.pattern = ENV['TEST_PATTERN'] || "test/**/*_spec.rb"
6 | end
7 |
8 | task :default => :test
9 |
10 |
--------------------------------------------------------------------------------
/api/config.ru:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'bundler/setup'
3 | require 'open-uri'
4 |
5 | Bundler.require
6 |
7 | set :public_folder, 'public'
8 |
9 | require './app.rb'
10 |
11 | run Sinatra::Application
12 |
13 |
--------------------------------------------------------------------------------
/api/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'rake'
4 |
5 | gem 'thin'
6 | gem 'sinatra'
7 | gem 'httparty'
8 | gem 'meme_captain'
9 | gem 'new_base_60'
10 |
11 | gem 'mysql2'
12 | gem 'sequel'
13 |
14 | group :development do
15 | gem 'shotgun'
16 | end
17 |
18 | group :test do
19 | gem 'minitest'
20 | end
21 |
--------------------------------------------------------------------------------
/api/schema.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE `memes` (
2 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
3 | `date` datetime DEFAULT NULL,
4 | `tz` varchar(50) DEFAULT NULL,
5 | `nick` varchar(50) DEFAULT NULL,
6 | `channel` varchar(50) DEFAULT NULL,
7 | `server` varchar(50) DEFAULT NULL,
8 | `filename` varchar(50) DEFAULT NULL,
9 | `text` text,
10 | PRIMARY KEY (`id`)
11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
12 |
--------------------------------------------------------------------------------
/api/README.md:
--------------------------------------------------------------------------------
1 | MemeCaptain API
2 | ===============
3 |
4 | This is a simple Sinatra app that wraps the [meme_captain](https://github.com/mmb/meme_captain) gem.
5 |
6 | To run this using passenger, create an nginx config block like the following:
7 |
8 | ---
9 | server {
10 | listen 80;
11 | server_name meme.loqi.me;
12 |
13 | root /web/zenircbot-meme/api/public;
14 | passenger_enabled on;
15 |
16 | location / {
17 | rewrite ^/([0-9a-zA-Z_]+\.jpg)$ /m/$1 break;
18 | passenger_enabled on;
19 | }
20 | }
21 | ---
22 |
23 |
--------------------------------------------------------------------------------
/api/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | daemons (1.3.1)
5 | eventmachine (1.2.7)
6 | httparty (0.16.2)
7 | multi_xml (>= 0.5.2)
8 | meme_captain (0.3.1)
9 | mime-types (~> 2.5)
10 | rmagick (~> 2.14.0)
11 | mime-types (2.99.3)
12 | minitest (5.11.3)
13 | multi_xml (0.6.0)
14 | mustermann (1.0.3)
15 | mysql2 (0.5.2)
16 | new_base_60 (1.1.2)
17 | rack (2.0.7)
18 | rack-protection (2.0.5)
19 | rack
20 | rake (12.3.3)
21 | rmagick (2.14.0)
22 | sequel (5.22.0)
23 | shotgun (0.9.2)
24 | rack (>= 1.0)
25 | sinatra (2.0.5)
26 | mustermann (~> 1.0)
27 | rack (~> 2.0)
28 | rack-protection (= 2.0.5)
29 | tilt (~> 2.0)
30 | thin (1.7.2)
31 | daemons (~> 1.0, >= 1.0.9)
32 | eventmachine (~> 1.0, >= 1.0.4)
33 | rack (>= 1, < 3)
34 | tilt (2.0.9)
35 |
36 | PLATFORMS
37 | ruby
38 |
39 | DEPENDENCIES
40 | httparty
41 | meme_captain
42 | minitest
43 | mysql2
44 | new_base_60
45 | rake
46 | sequel
47 | shotgun
48 | sinatra
49 | thin
50 |
51 | BUNDLED WITH
52 | 1.16.2
53 |
--------------------------------------------------------------------------------
/api/lib/meme-match.rb:
--------------------------------------------------------------------------------
1 | class MemeMatch
2 |
3 | def self.split(input)
4 | top = nil
5 | bottom = nil
6 |
7 | split = input.split '|'
8 |
9 | if split.length == 1
10 | if input[-1] == "|"
11 | top = split[0]
12 | else
13 | bottom = split[0]
14 | end
15 | elsif split.length == 2
16 | top = split[0]
17 | bottom = split[1]
18 | end
19 |
20 | top = top.gsub(/[. \|]+$/,'') if top
21 | bottom = bottom.gsub(/[. \|]+$/,'').gsub(/^[| ]+/,'') if bottom
22 |
23 | top = nil if top == ""
24 | bottom = nil if bottom == ""
25 |
26 | {
27 | top: top,
28 | bottom: bottom
29 | }
30 | end
31 |
32 | @@memes = {}
33 |
34 | def self.load_memes
35 | @@memes = JSON.parse IO.read File.dirname(__FILE__) + '/../memes.json'
36 | end
37 |
38 | def self.memes
39 | @@memes['memes']
40 | end
41 |
42 | def self.match_meme(input)
43 | self.memes.each do |meme|
44 | if match=Regexp.new(meme['regex'], true).match(input)
45 | return {
46 | top: match.captures[0],
47 | bottom: match.captures[1],
48 | img: meme['img']
49 | }
50 | end
51 | end
52 | nil
53 | end
54 |
55 | end
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Meme API
2 | ========
3 | An API and TikTokBot integration that implements a !meme command to generate a meme image
4 |
5 | Usage
6 | =====
7 |
8 | You can explicitly invoke the meme generator from Slack or IRC by saying `!meme ...`
9 |
10 | The top text is the message before the first '.' is encountered. Unless there is no '.', then all of the text is put on the bottom of the image. You can also explicitly set the top and bottom text by separating with `|`.
11 |
12 | The default image is the Aliens guy if no image is specified:
13 |
14 |
15 |
16 | You can override the default image by putting an image url or search term after the message surrounded by [].
17 |
18 | Examples
19 | ========
20 | !meme I don't always test my code. | But when I do, I do it in production [http://meme.loqi.me/img/most_interesting.jpg]
21 |
22 |
23 |
24 | !meme Top | Bottom [http://meme.loqi.me/img/most_interesting.jpg]
25 |
26 | !meme Top | Bottom [largest bunny]
27 |
28 | Auto-detecting memes
29 | ====================
30 |
31 | Certain sentences will be auto-matched according to the regexes in [memes.json](api/memes.json), and memes will be created without explicitly using the !meme command.
32 |
33 | Feel free to add new meme templates to the config!
34 |
35 |
--------------------------------------------------------------------------------
/api/test/regex_spec.rb:
--------------------------------------------------------------------------------
1 | require_relative './init'
2 |
3 | describe MemeMatch do
4 |
5 | def assert_top_and_bottom(match)
6 | match[:top].must_equal 'top'
7 | match[:bottom].must_equal 'bottom'
8 | end
9 |
10 | def assert_bottom_only(match)
11 | match[:top].must_equal nil
12 | match[:bottom].must_equal 'bottom'
13 | end
14 |
15 | def assert_top_only(match)
16 | match[:top].must_equal 'top'
17 | match[:bottom].must_equal nil
18 | end
19 |
20 | it 'matches top and bottom' do
21 | assert_top_and_bottom MemeMatch.split('top... | bottom.')
22 | assert_top_and_bottom MemeMatch.split('top... | bottom')
23 | assert_top_and_bottom MemeMatch.split('top. | bottom.')
24 | assert_top_and_bottom MemeMatch.split('top. | bottom')
25 | assert_top_and_bottom MemeMatch.split('top | bottom.')
26 | assert_top_and_bottom MemeMatch.split('top | bottom')
27 | end
28 |
29 | it 'matches bottom' do
30 | assert_bottom_only MemeMatch.split('bottom')
31 | assert_bottom_only MemeMatch.split('bottom.')
32 | assert_bottom_only MemeMatch.split('|bottom')
33 | assert_bottom_only MemeMatch.split('| bottom')
34 | end
35 |
36 | it 'matches top' do
37 | assert_top_only MemeMatch.split('top|')
38 | assert_top_only MemeMatch.split('top |')
39 | assert_top_only MemeMatch.split('top. |')
40 | end
41 |
42 | it 'matches full sentence' do
43 | match = MemeMatch.split('line one. with a period. | line two.')
44 | match[:top].must_equal 'line one. with a period'
45 | match[:bottom].must_equal 'line two'
46 | end
47 |
48 | MemeMatch.load_memes
49 | MemeMatch.memes.each do |meme|
50 | it "matches #{meme['img']}" do
51 | result = MemeMatch.match_meme meme['test']
52 | result.wont_be_nil
53 | result[:img].must_equal meme['img']
54 | end
55 | end
56 |
57 | end
58 |
--------------------------------------------------------------------------------
/api/memes.json:
--------------------------------------------------------------------------------
1 | {"memes": [
2 | {
3 | "regex": "(^I don't (?:always|normally|usually) .+) (but when I do,? .+$)",
4 | "img": "most_interesting.jpg",
5 | "test": "I don't always test my code, but when I do, I do it in production."
6 | },
7 | {
8 | "regex": "^([\\w:]+(?: [\\w:]+)?) (all the [\\w:]+s)[!\\.]*$",
9 | "img": "all_the_things.jpg",
10 | "test": "Refactor all the things!"
11 | },
12 | {
13 | "regex": "(^one does not simply) (.+$)",
14 | "img": "boromir.jpg",
15 | "test": "One does not simply meme in IRC."
16 | },
17 | {
18 | "regex": "(^not sure if [^\\|]+)(?: \\|)? (or .+$)",
19 | "img": "fry.png",
20 | "test": "Not sure if this is working, or is awesome."
21 | },
22 | {
23 | "regex": "(^yo,? (?:dawg|dog)[\\.,]* I hea?rd (?:you|u) like .+) (so (?:i|we) .+$)",
24 | "img": "xzibit.jpg",
25 | "test": "Yo dawg I herd you like regex. so we put a regex in yo regex so you can match while you match."
26 | },
27 | {
28 | "regex": "(^.+) (is too damn .+[!\\.]?$)",
29 | "img": "too_damn_high.jpg",
30 | "test": "The amount of memes in this channel is too damn high!"
31 | },
32 | {
33 | "regex": "^(brace yourselves)[, ]+(.+ (?:is|are) coming)[!\\.]?$",
34 | "img": "ned_stark.jpg",
35 | "test": "Brace yourselves the memes are coming."
36 | },
37 | {
38 | "regex": "(^what if) (.+[\\?!]+$)",
39 | "img": "conspiracy_keanu.jpg",
40 | "test": "What if space nachos?!"
41 | },
42 | {
43 | "regex": "(^.+) (and you should feel bad\\.?$)",
44 | "img": "you_should_feel_bad.jpg",
45 | "test": "This meme is bad; and you should feel bad."
46 | },
47 | {
48 | "regex": "(^.+) (y u no .+$)",
49 | "img": "y_u_no.jpg",
50 | "test": "IRC y u no do memes yourself?"
51 | },
52 | {
53 | "regex": "(^am i the only one around here) (.+$)",
54 | "img": "walter.jpg",
55 | "test": "Am I the only one around here who gives a shit about the rules?!"
56 | },
57 | {
58 | "regex": "(^.+) (so hot right now[\\.!]*$)",
59 | "img": "mugatu.jpg",
60 | "test": "Memes, so hot right now."
61 | },
62 | {
63 | "regex": "(^.+) (is strong with this one[!\\.]*$)",
64 | "img": "emperor.jpg",
65 | "test": "The force is strong with this one."
66 | },
67 | {
68 | "regex": "(^this is) (.{1,50}!$)",
69 | "img": "sparta.jpg",
70 | "test": "This is IRC!"
71 | },
72 | {
73 | "regex": "(.+) (\\w+ go(?:es)? to (?:eleven|11))!?$",
74 | "img": "goes_to_eleven.jpg",
75 | "test": "The memes, they go to eleven!"
76 | },
77 | {
78 | "regex": "^()(fantastic)!*$",
79 | "img": "fantastic-doctor.jpg",
80 | "test": "fantastic!"
81 | },
82 | {
83 | "regex": "(^enough with) (.+!$)",
84 | "img": "batman-slap.jpg",
85 | "test": "Enough with the memes!"
86 | },
87 | {
88 | "regex": "(^nobody expects) (.+$)",
89 | "img": "inquisition.jpg",
90 | "test": "Nobody expects a pull request!"
91 | },
92 | {
93 | "regex": "(^.+ (?:is|are) better), (no .+ (?:is|are) better[!\\.])",
94 | "img": "shampoo-is-better.jpg",
95 | "test": "Shampoo is better, no conditioner is better!"
96 | },
97 | {
98 | "regex": "(^if .+) (I would be so happy[!\\.]?)$",
99 | "img": "craig-happy.jpg",
100 | "test": "If it was warmer, I would be so happy"
101 | },
102 | {
103 | "regex": "(.+) (over [0-9]+[\\.!]*)$",
104 | "img": "over_9000.jpg",
105 | "test": "His karma, it's over 9000!"
106 | },
107 | {
108 | "regex": "^(and then (?:we|I) told (?:him|her|them),?) (.+)$",
109 | "img": "laughing-men.jpg",
110 | "test": "And then we told him we had consensus!"
111 | },
112 | {
113 | "regex": "^(.+ (?:is|are)(?: ?n['o]?t) the .+) (you'?re looking for)",
114 | "img": "kenobi.gif",
115 | "test": "These are not the droids you're looking for"
116 | },
117 | {
118 | "regex": "^(.+) ([^ ]+ kermit panic\\?*)$",
119 | "img": "kermit-panic.gif",
120 | "test": "did you immediately kermit panic?"
121 | },
122 | {
123 | "regex": "^([^,]+),? (panic!+?)$",
124 | "img": "kermit-panic.gif",
125 | "test": "ok, panic!!"
126 | },
127 | {
128 | "regex": "([^\\|]+)(?: \\|)? (I will find .+$)",
129 | "img": "taken.jpg",
130 | "test": "I don't know who you are. I will find you and add you to my LinkedIn."
131 | },
132 | {
133 | "regex": "^(i .+),? (i am the .+)$",
134 | "img": "i_am_the_law.jpg",
135 | "test": "I can't break the cloud, I am the cloud!"
136 | },
137 | {
138 | "regex": "^(oh really.+[,\? ]+?)(tell me more.+)",
139 | "img": "wonka.jpg",
140 | "test": "oh really? tell me more..."
141 | }
142 | ]}
143 |
--------------------------------------------------------------------------------
/api/app.rb:
--------------------------------------------------------------------------------
1 | require_relative './lib/meme-match'
2 | require 'json'
3 |
4 | MemeMatch.load_memes
5 | $config = YAML.load_file 'config.yml'
6 |
7 | DB = Sequel.connect $config['database']
8 |
9 | get '/g' do
10 |
11 | if !params[:u].match(/^http:/)
12 | return "Invalid image url"
13 | end
14 |
15 | open(params[:u], 'rb') do |f|
16 | begin
17 | i = MemeCaptain.meme_top_bottom(f, params[:t1], params[:t2], :font => './Impact.ttf')
18 | if(params[:u].match(/\.gif$/))
19 | ext = "gif"
20 | else
21 | ext = "jpg"
22 | end
23 | filename = "#{DateTime.now.to_sxg}#{SecureRandom.random_number(60**5).to_sxg}.#{ext}"
24 | i.write("./public/m/#{filename}")
25 | headers 'Content-type' => 'application/json'
26 | {imageUrl: "http://#{request.host}/#{filename}"}.to_json
27 | rescue => e
28 | {error: e.message}
29 | end
30 | end
31 |
32 | end
33 |
34 | post '/message' do
35 |
36 | # TikTokBot posts JSON
37 | request.body.rewind
38 | @params = JSON.parse request.body.read
39 |
40 | top = nil
41 | bottom = nil
42 | img = nil
43 |
44 | if match=/^!meme (.+)/.match(@params['content'])
45 | # user explicitly requested a meme
46 | text = match.captures[0]
47 | # check if they specified an image or image search
48 | if match=/(.+) \[(https?:\/\/[^\] ]+)\]$/.match(text)
49 | text = match.captures[0]
50 | img = match.captures[1]
51 | split = MemeMatch.split text
52 | top = split[:top]
53 | bottom = split[:bottom]
54 | elsif match=/(.+) \[([^\]]+)\]$/.match(text)
55 | text = match.captures[0]
56 | search = match.captures[1]
57 | split = MemeMatch.split text
58 | top = split[:top]
59 | bottom = split[:bottom]
60 | img = image_search search
61 | else
62 | # check if the meme matches a pattern
63 | if match=MemeMatch.match_meme(text)
64 | top = match[:top]
65 | bottom = match[:bottom]
66 | img = match[:img]
67 | else
68 | # If it doesn't, make a meme anyway because it was explicitly requested
69 | split = MemeMatch.split text
70 | top = split[:top]
71 | bottom = split[:bottom]
72 | img = "aliens.jpg" # default
73 | end
74 | end
75 | else
76 | # all other chat messages are sent here, check if the line matches a meme pattern
77 | if match=MemeMatch.match_meme(@params['content'])
78 | top = match[:top]
79 | bottom = match[:bottom]
80 | img = match[:img]
81 | end
82 | end
83 |
84 | if img && !img.match(/^https?:\/\//)
85 | img = "./public/img/#{img}"
86 | end
87 |
88 | headers 'Content-type' => 'application/json'
89 | if img
90 | # If the message is from Slack, send back a typing indicator
91 | if @params['network'] == 'slack'
92 | HTTParty.post @params['response_url'], {
93 | body: {action: 'typing'}
94 | }
95 | end
96 |
97 | meme = make_meme img, top, bottom
98 |
99 | DB[:memes] << {
100 | date: DateTime.now.strftime('%Y-%m-%d %H:%M:%S'),
101 | tz: @params['author']['tz'],
102 | nick: @params['author']['nickname'],
103 | channel: @params['channel']['name'],
104 | server: @params['server'],
105 | filename: meme[:filename],
106 | text: @params['content']
107 | }
108 |
109 | # If the message is from Slack, respond with the image as an attachment
110 | if @params['network'] == 'slack'
111 | if !top.nil? && !bottom.nil?
112 | title = "#{top} #{bottom}"
113 | elsif !top.nil?
114 | title = top
115 | else
116 | title = bottom
117 | end
118 |
119 | # response = {
120 | # attachments: [
121 | # {
122 | # "fallback": meme[:url],
123 | # "title": title,
124 | # "image_url": meme[:url]
125 | # }
126 | # ]
127 | # }.to_json
128 | response = {
129 | file: {
130 | "title": title,
131 | "filename": title,
132 | "url": meme[:url]
133 | }
134 | }.to_json
135 | puts response
136 | response
137 | else
138 | # otherwise respond with a link to the image
139 | {content: meme[:url]}.to_json
140 | end
141 | else
142 | {error: "no image"}.to_json
143 | end
144 | end
145 |
146 | def make_meme(img, top, bottom)
147 | open(img, 'rb') do |f|
148 | begin
149 | i = MemeCaptain.meme_top_bottom(f, top, bottom, :font => './Impact.ttf')
150 | if(img.match(/\.gif$/))
151 | ext = "gif"
152 | else
153 | ext = "jpg"
154 | end
155 | filename = "#{DateTime.now.to_sxg}#{SecureRandom.random_number(60**5).to_sxg}.#{ext}"
156 | i.write("./public/m/#{filename}")
157 | {url: "#{$config['base_url']}/m/#{filename}", filename: filename}
158 | rescue => e
159 | {error: e.message}
160 | end
161 | end
162 | end
163 |
164 |
165 | def image_search(term)
166 | query = URI.encode_www_form({
167 | q: term,
168 | fileType: 'jpg',
169 | imgColorType: 'color',
170 | imgSize: 'large',
171 | imgType: 'photo',
172 | num: '1',
173 | safe: 'medium',
174 | searchType: 'image',
175 | cx: $config['google_cx'],
176 | key: $config['google_server_key']
177 | })
178 | response = HTTParty.get "https://www.googleapis.com/customsearch/v1?#{query}"
179 | if response && response.parsed_response
180 | r = response.parsed_response
181 | if r['items'] && r['items'].length > 0
182 | return r['items'][0]['link']
183 | end
184 | end
185 | nil
186 | end
187 |
188 |
--------------------------------------------------------------------------------