about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2016-09-12 09:14:57 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2016-09-12 09:14:57 -0400
commitae39a502468a571928ebbdec05e90ab5874bf319 (patch)
treeb843426a4ffb93270f143b5bac54da5847ae228d
parente85f3fbd08f12c5d319479f3c8aa369e0360e355 (diff)
downloaddifference-ae39a502468a571928ebbdec05e90ab5874bf319.tar.gz
difference-ae39a502468a571928ebbdec05e90ab5874bf319.tar.bz2
difference-ae39a502468a571928ebbdec05e90ab5874bf319.zip
Updated libtwitter++ (new API, and fixing a curlcpp crash)
Also changed to use C++ APIs for randomization and sleeping.
-rw-r--r--difference.cpp313
m---------vendor/libtwittercpp0
2 files changed, 152 insertions, 161 deletions
diff --git a/difference.cpp b/difference.cpp index 3d3bb18..c2e3b37 100644 --- a/difference.cpp +++ b/difference.cpp
@@ -1,16 +1,17 @@
1#include <verbly.h> 1#include <verbly.h>
2#include <twitter.h> 2#include <twitter.h>
3#include <curl_easy.h> 3#include <curl_easy.h>
4#include <curl_header.h>
4#include <list> 5#include <list>
5#include <set> 6#include <set>
6#include <vector> 7#include <vector>
7#include <algorithm> 8#include <algorithm>
8#include <cstdlib>
9#include <ctime>
10#include <Magick++.h> 9#include <Magick++.h>
11#include <iostream> 10#include <iostream>
12#include <yaml-cpp/yaml.h> 11#include <yaml-cpp/yaml.h>
13#include <unistd.h> 12#include <chrono>
13#include <thread>
14#include <random>
14 15
15std::string capitalize(std::string input) 16std::string capitalize(std::string input)
16{ 17{
@@ -65,7 +66,8 @@ bool downloadImage(std::string url, curl::curl_header headers, Magick::Blob& img
65 return false; 66 return false;
66 } 67 }
67 68
68 if (std::string(imghandle.get_info<CURLINFO_CONTENT_TYPE>().get()).substr(0, 6) != "image/") 69 std::string content_type = imghandle.get_info<CURLINFO_CONTENT_TYPE>().get();
70 if (content_type.substr(0, 6) != "image/")
69 { 71 {
70 return false; 72 return false;
71 } 73 }
@@ -85,7 +87,6 @@ bool downloadImage(std::string url, curl::curl_header headers, Magick::Blob& img
85 87
86int main(int argc, char** argv) 88int main(int argc, char** argv)
87{ 89{
88 srand(time(NULL));
89 Magick::InitializeMagick(nullptr); 90 Magick::InitializeMagick(nullptr);
90 91
91 int delay = 60 * 60; 92 int delay = 60 * 60;
@@ -99,6 +100,9 @@ int main(int argc, char** argv)
99 100
100 twitter::client client(auth); 101 twitter::client client(auth);
101 102
103 std::random_device random_device;
104 std::mt19937 random_engine{random_device()};
105
102 verbly::data database("data.sqlite3"); 106 verbly::data database("data.sqlite3");
103 107
104 auto whitelist = database.nouns(); 108 auto whitelist = database.nouns();
@@ -149,194 +153,181 @@ int main(int argc, char** argv)
149 std::cout << "Started!" << std::endl; 153 std::cout << "Started!" << std::endl;
150 for (;;) 154 for (;;)
151 { 155 {
152 std::cout << "Generating noun..." << std::endl; 156 try
153 verbly::noun pictured = database.nouns().full_hyponym_of(whitefilter).at_least_n_images(2).random().limit(1).run().front(); 157 {
154 std::cout << "Noun: " << pictured.singular_form() << std::endl; 158 std::cout << "Generating noun..." << std::endl;
155 std::cout << "Getting URLs..." << std::endl; 159 verbly::noun pictured = database.nouns().full_hyponym_of(whitefilter).at_least_n_images(2).random().limit(1).run().front();
156 std::ostringstream lstbuf; 160 std::cout << "Noun: " << pictured.singular_form() << std::endl;
157 curl::curl_ios<std::ostringstream> lstios(lstbuf); 161 std::cout << "Getting URLs..." << std::endl;
158 curl::curl_easy lsthandle(lstios); 162 std::ostringstream lstbuf;
159 std::string lsturl = pictured.imagenet_url(); 163 curl::curl_ios<std::ostringstream> lstios(lstbuf);
160 lsthandle.add<CURLOPT_URL>(lsturl.c_str()); 164 curl::curl_easy lsthandle(lstios);
161 try { 165 std::string lsturl = pictured.imagenet_url();
166 lsthandle.add<CURLOPT_URL>(lsturl.c_str());
162 lsthandle.perform(); 167 lsthandle.perform();
163 } catch (curl::curl_easy_exception error) {
164 error.print_traceback();
165 sleep(delay);
166
167 continue;
168 }
169 168
170 if (lsthandle.get_info<CURLINFO_RESPONSE_CODE>().get() != 200) 169 if (lsthandle.get_info<CURLINFO_RESPONSE_CODE>().get() != 200)
171 { 170 {
172 std::cout << "Could not get URLs" << std::endl; 171 std::cout << "Could not get URLs" << std::endl;
173 continue; 172 continue;
174 } 173 }
175 174
176 std::cout << "Got URLs." << std::endl; 175 std::cout << "Got URLs." << std::endl;
177 std::string lstdata = lstbuf.str(); 176 std::string lstdata = lstbuf.str();
178 auto lstlist = verbly::split<std::list<std::string>>(lstdata, "\r\n"); 177 auto lstlist = verbly::split<std::list<std::string>>(lstdata, "\r\n");
179 std::set<std::string> lstset; 178 std::set<std::string> lstset;
180 for (auto url : lstlist) 179 for (auto url : lstlist)
181 { 180 {
182 lstset.insert(url); 181 lstset.insert(url);
183 } 182 }
184 183
185 if (lstset.size() < 2) 184 if (lstset.size() < 2)
186 { 185 {
187 continue; 186 continue;
188 } 187 }
189 188
190 std::vector<std::string> lstvec; 189 std::vector<std::string> lstvec;
191 for (auto url : lstset) 190 for (auto url : lstset)
192 { 191 {
193 lstvec.push_back(url); 192 lstvec.push_back(url);
194 } 193 }
195 194
196 std::random_shuffle(std::begin(lstvec), std::end(lstvec)); 195 std::shuffle(std::begin(lstvec), std::end(lstvec), random_engine);
197 196
198 Magick::Blob img1; 197 Magick::Blob img1;
199 Magick::Image pic1; 198 Magick::Image pic1;
200 bool success = false; 199 bool success = false;
201 int curind = 0; 200 int curind = 0;
202 for (; curind < lstvec.size(); curind++) 201 for (; curind < lstvec.size(); curind++)
203 {
204 if (downloadImage(lstvec[curind], headers, img1, pic1))
205 { 202 {
206 success = true; 203 if (downloadImage(lstvec[curind], headers, img1, pic1))
207 break; 204 {
205 success = true;
206 break;
207 }
208 } 208 }
209 }
210 209
211 if (!success) 210 if (!success)
212 { 211 {
213 continue; 212 continue;
214 } 213 }
215 214
216 success = false; 215 success = false;
217 Magick::Blob img2; 216 Magick::Blob img2;
218 Magick::Image pic2; 217 Magick::Image pic2;
219 for (curind++; curind < lstvec.size(); curind++) 218 for (curind++; curind < lstvec.size(); curind++)
220 {
221 if (downloadImage(lstvec[curind], headers, img2, pic2))
222 { 219 {
223 success = true; 220 if (downloadImage(lstvec[curind], headers, img2, pic2))
224 break; 221 {
222 success = true;
223 break;
224 }
225 } 225 }
226 }
227 226
228 if (!success) 227 if (!success)
229 { 228 {
230 continue; 229 continue;
231 } 230 }
232 231
233 std::string ant1, ant2; 232 std::string ant1, ant2;
234 if (rand()%2==0) 233 std::uniform_int_distribution<int> coinflip(0, 1);
235 { 234 if (coinflip(random_engine)==0)
236 verbly::noun n1 = database.nouns().has_antonyms().random().limit(1).run().front(); 235 {
237 verbly::noun n2 = n1.antonyms().random().limit(1).run().front(); 236 verbly::noun n1 = database.nouns().has_antonyms().random().limit(1).run().front();
238 ant1 = n1.singular_form(); 237 verbly::noun n2 = n1.antonyms().random().limit(1).run().front();
239 ant2 = n2.singular_form(); 238 ant1 = n1.singular_form();
240 } else { 239 ant2 = n2.singular_form();
241 verbly::adjective a1 = database.adjectives().has_antonyms().random().limit(1).run().front(); 240 } else {
242 verbly::adjective a2 = a1.antonyms().random().limit(1).run().front(); 241 verbly::adjective a1 = database.adjectives().has_antonyms().random().limit(1).run().front();
243 ant1 = a1.base_form(); 242 verbly::adjective a2 = a1.antonyms().random().limit(1).run().front();
244 ant2 = a2.base_form(); 243 ant1 = a1.base_form();
245 } 244 ant2 = a2.base_form();
245 }
246 246
247 if (pic1.columns() < 320) 247 if (pic1.columns() < 320)
248 { 248 {
249 pic1.zoom(Magick::Geometry(320, pic1.rows() * 320 / pic1.columns(), 0, 0)); 249 pic1.zoom(Magick::Geometry(320, pic1.rows() * 320 / pic1.columns(), 0, 0));
250 } 250 }
251 251
252 if (pic2.columns() < 320) 252 if (pic2.columns() < 320)
253 { 253 {
254 pic2.zoom(Magick::Geometry(320, pic2.rows() * 320 / pic2.columns(), 0, 0)); 254 pic2.zoom(Magick::Geometry(320, pic2.rows() * 320 / pic2.columns(), 0, 0));
255 } 255 }
256 256
257 int width = std::min(pic1.columns(), pic2.columns()); 257 int width = std::min(pic1.columns(), pic2.columns());
258 int height = std::min(pic1.rows(), pic2.rows()); 258 int height = std::min(pic1.rows(), pic2.rows());
259 Magick::Geometry geo1(width, height, pic1.columns()/2 - width/2, pic1.rows()/2 - height/2); 259 Magick::Geometry geo1(width, height, pic1.columns()/2 - width/2, pic1.rows()/2 - height/2);
260 Magick::Geometry geo2(width, height, pic2.columns()/2 - width/2, pic2.rows()/2 - height/2); 260 Magick::Geometry geo2(width, height, pic2.columns()/2 - width/2, pic2.rows()/2 - height/2);
261 pic1.crop(geo1); 261 pic1.crop(geo1);
262 pic2.crop(geo2); 262 pic2.crop(geo2);
263 263
264 Magick::Image composite(Magick::Geometry(width*2, height, 0, 0), "white"); 264 Magick::Image composite(Magick::Geometry(width*2, height, 0, 0), "white");
265 composite.draw(Magick::DrawableCompositeImage(0, 0, pic1)); 265 composite.draw(Magick::DrawableCompositeImage(0, 0, pic1));
266 composite.draw(Magick::DrawableCompositeImage(width, 0, pic2)); 266 composite.draw(Magick::DrawableCompositeImage(width, 0, pic2));
267 composite.font("@coolvetica.ttf"); 267 composite.font("@coolvetica.ttf");
268 268
269 double fontsize = 72; 269 double fontsize = 72;
270 for (;;) 270 for (;;)
271 {
272 composite.fontPointsize(fontsize);
273
274 Magick::TypeMetric metric;
275 composite.fontTypeMetrics(ant1, &metric);
276 if (metric.textWidth() > 300)
277 { 271 {
278 fontsize -= 0.5; 272 composite.fontPointsize(fontsize);
279 continue;
280 }
281 273
282 composite.fontTypeMetrics(ant2, &metric); 274 Magick::TypeMetric metric;
283 if (metric.textWidth() > 300) 275 composite.fontTypeMetrics(ant1, &metric);
284 { 276 if (metric.textWidth() > 300)
285 fontsize -= 0.5; 277 {
286 continue; 278 fontsize -= 0.5;
287 } 279 continue;
280 }
288 281
289 break; 282 composite.fontTypeMetrics(ant2, &metric);
290 } 283 if (metric.textWidth() > 300)
291 284 {
292 Magick::TypeMetric metric; 285 fontsize -= 0.5;
293 composite.fontTypeMetrics(ant1, &metric); 286 continue;
294 int y = rand() % ((int)(composite.rows() - 40 - metric.textHeight())) + 20; 287 }
295 y = composite.rows() - y; 288
296 int x1 = (width - 40 - metric.textWidth())/2+20; 289 break;
297 composite.fontTypeMetrics(ant2, &metric); 290 }
298 int x2 = (width - 40 - metric.textWidth())/2+20+width;
299 composite.strokeColor("white");
300 composite.strokeWidth(2);
301 composite.antiAlias(false);
302 composite.draw(Magick::DrawableText(x1, y, ant1));
303 composite.draw(Magick::DrawableText(x2, y, ant2));
304 291
305 composite.magick("png"); 292 Magick::TypeMetric metric;
293 composite.fontTypeMetrics(ant1, &metric);
294 std::uniform_int_distribution<int> rowdist(20, (int)(composite.rows() - 19 - metric.textHeight()));
295 int y = rowdist(random_engine);
296 y = composite.rows() - y;
297 int x1 = (width - 40 - metric.textWidth())/2+20;
298 composite.fontTypeMetrics(ant2, &metric);
299 int x2 = (width - 40 - metric.textWidth())/2+20+width;
300 composite.strokeColor("white");
301 composite.strokeWidth(2);
302 composite.antiAlias(false);
303 composite.draw(Magick::DrawableText(x1, y, ant1));
304 composite.draw(Magick::DrawableText(x2, y, ant2));
306 305
307 Magick::Blob outputimg; 306 composite.magick("png");
308 composite.write(&outputimg);
309 307
310 std::cout << "Generated image!" << std::endl << "Tweeting..." << std::endl; 308 Magick::Blob outputimg;
309 composite.write(&outputimg);
311 310
312 std::stringstream msg; 311 std::cout << "Generated image!" << std::endl << "Tweeting..." << std::endl;
313 msg << capitalize(ant1);
314 msg << " vs. ";
315 msg << capitalize(ant2);
316 312
317 long media_id; 313 std::stringstream msg;
318 twitter::response resp = client.uploadMedia("image/png", (const char*) outputimg.data(), outputimg.length(), media_id); 314 msg << capitalize(ant1);
319 if (resp != twitter::response::ok) 315 msg << " vs. ";
316 msg << capitalize(ant2);
317
318 long media_id = client.uploadMedia("image/png", (const char*) outputimg.data(), outputimg.length());
319 client.updateStatus(msg.str(), {media_id});
320
321 std::cout << "Done!" << std::endl << "Waiting..." << std::endl << std::endl;
322 } catch (const curl::curl_easy_exception& error)
320 { 323 {
321 std::cout << "Twitter error while uploading image: " << resp << std::endl; 324 error.print_traceback();
322 sleep(delay); 325 } catch (const twitter::twitter_error& e)
323
324 continue;
325 }
326
327 twitter::tweet tw;
328 resp = client.updateStatus(msg.str(), tw, {media_id});
329 if (resp != twitter::response::ok)
330 { 326 {
331 std::cout << "Twitter error while tweeting: " << resp << std::endl; 327 std::cout << "Twitter error: " << e.what() << std::endl;
332 sleep(delay);
333
334 continue;
335 } 328 }
336 329
337 std::cout << "Done!" << std::endl << "Waiting..." << std::endl << std::endl; 330 std::this_thread::sleep_for(std::chrono::seconds(delay));
338
339 sleep(delay);
340 } 331 }
341 332
342 return 0; 333 return 0;
diff --git a/vendor/libtwittercpp b/vendor/libtwittercpp
Subproject a3d1ed08683c75c22d13f25e33f4333debf4f71 Subproject a2d28cfbd7ab8ea71a802f06c2ae76c62decb02