From ae39a502468a571928ebbdec05e90ab5874bf319 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Mon, 12 Sep 2016 09:14:57 -0400 Subject: Updated libtwitter++ (new API, and fixing a curlcpp crash) Also changed to use C++ APIs for randomization and sleeping. --- difference.cpp | 313 +++++++++++++++++++++++++-------------------------- vendor/libtwittercpp | 2 +- 2 files changed, 153 insertions(+), 162 deletions(-) diff --git a/difference.cpp b/difference.cpp index 3d3bb18..c2e3b37 100644 --- a/difference.cpp +++ b/difference.cpp @@ -1,16 +1,17 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include #include -#include +#include +#include +#include std::string capitalize(std::string input) { @@ -65,7 +66,8 @@ bool downloadImage(std::string url, curl::curl_header headers, Magick::Blob& img return false; } - if (std::string(imghandle.get_info().get()).substr(0, 6) != "image/") + std::string content_type = imghandle.get_info().get(); + if (content_type.substr(0, 6) != "image/") { return false; } @@ -85,7 +87,6 @@ bool downloadImage(std::string url, curl::curl_header headers, Magick::Blob& img int main(int argc, char** argv) { - srand(time(NULL)); Magick::InitializeMagick(nullptr); int delay = 60 * 60; @@ -99,6 +100,9 @@ int main(int argc, char** argv) twitter::client client(auth); + std::random_device random_device; + std::mt19937 random_engine{random_device()}; + verbly::data database("data.sqlite3"); auto whitelist = database.nouns(); @@ -149,194 +153,181 @@ int main(int argc, char** argv) std::cout << "Started!" << std::endl; for (;;) { - std::cout << "Generating noun..." << std::endl; - verbly::noun pictured = database.nouns().full_hyponym_of(whitefilter).at_least_n_images(2).random().limit(1).run().front(); - std::cout << "Noun: " << pictured.singular_form() << std::endl; - std::cout << "Getting URLs..." << std::endl; - std::ostringstream lstbuf; - curl::curl_ios lstios(lstbuf); - curl::curl_easy lsthandle(lstios); - std::string lsturl = pictured.imagenet_url(); - lsthandle.add(lsturl.c_str()); - try { + try + { + std::cout << "Generating noun..." << std::endl; + verbly::noun pictured = database.nouns().full_hyponym_of(whitefilter).at_least_n_images(2).random().limit(1).run().front(); + std::cout << "Noun: " << pictured.singular_form() << std::endl; + std::cout << "Getting URLs..." << std::endl; + std::ostringstream lstbuf; + curl::curl_ios lstios(lstbuf); + curl::curl_easy lsthandle(lstios); + std::string lsturl = pictured.imagenet_url(); + lsthandle.add(lsturl.c_str()); lsthandle.perform(); - } catch (curl::curl_easy_exception error) { - error.print_traceback(); - sleep(delay); - - continue; - } - if (lsthandle.get_info().get() != 200) - { - std::cout << "Could not get URLs" << std::endl; - continue; - } + if (lsthandle.get_info().get() != 200) + { + std::cout << "Could not get URLs" << std::endl; + continue; + } - std::cout << "Got URLs." << std::endl; - std::string lstdata = lstbuf.str(); - auto lstlist = verbly::split>(lstdata, "\r\n"); - std::set lstset; - for (auto url : lstlist) - { - lstset.insert(url); - } + std::cout << "Got URLs." << std::endl; + std::string lstdata = lstbuf.str(); + auto lstlist = verbly::split>(lstdata, "\r\n"); + std::set lstset; + for (auto url : lstlist) + { + lstset.insert(url); + } - if (lstset.size() < 2) - { - continue; - } + if (lstset.size() < 2) + { + continue; + } - std::vector lstvec; - for (auto url : lstset) - { - lstvec.push_back(url); - } + std::vector lstvec; + for (auto url : lstset) + { + lstvec.push_back(url); + } - std::random_shuffle(std::begin(lstvec), std::end(lstvec)); + std::shuffle(std::begin(lstvec), std::end(lstvec), random_engine); - Magick::Blob img1; - Magick::Image pic1; - bool success = false; - int curind = 0; - for (; curind < lstvec.size(); curind++) - { - if (downloadImage(lstvec[curind], headers, img1, pic1)) + Magick::Blob img1; + Magick::Image pic1; + bool success = false; + int curind = 0; + for (; curind < lstvec.size(); curind++) { - success = true; - break; + if (downloadImage(lstvec[curind], headers, img1, pic1)) + { + success = true; + break; + } } - } - if (!success) - { - continue; - } + if (!success) + { + continue; + } - success = false; - Magick::Blob img2; - Magick::Image pic2; - for (curind++; curind < lstvec.size(); curind++) - { - if (downloadImage(lstvec[curind], headers, img2, pic2)) + success = false; + Magick::Blob img2; + Magick::Image pic2; + for (curind++; curind < lstvec.size(); curind++) { - success = true; - break; + if (downloadImage(lstvec[curind], headers, img2, pic2)) + { + success = true; + break; + } } - } - if (!success) - { - continue; - } + if (!success) + { + continue; + } - std::string ant1, ant2; - if (rand()%2==0) - { - verbly::noun n1 = database.nouns().has_antonyms().random().limit(1).run().front(); - verbly::noun n2 = n1.antonyms().random().limit(1).run().front(); - ant1 = n1.singular_form(); - ant2 = n2.singular_form(); - } else { - verbly::adjective a1 = database.adjectives().has_antonyms().random().limit(1).run().front(); - verbly::adjective a2 = a1.antonyms().random().limit(1).run().front(); - ant1 = a1.base_form(); - ant2 = a2.base_form(); - } + std::string ant1, ant2; + std::uniform_int_distribution coinflip(0, 1); + if (coinflip(random_engine)==0) + { + verbly::noun n1 = database.nouns().has_antonyms().random().limit(1).run().front(); + verbly::noun n2 = n1.antonyms().random().limit(1).run().front(); + ant1 = n1.singular_form(); + ant2 = n2.singular_form(); + } else { + verbly::adjective a1 = database.adjectives().has_antonyms().random().limit(1).run().front(); + verbly::adjective a2 = a1.antonyms().random().limit(1).run().front(); + ant1 = a1.base_form(); + ant2 = a2.base_form(); + } - if (pic1.columns() < 320) - { - pic1.zoom(Magick::Geometry(320, pic1.rows() * 320 / pic1.columns(), 0, 0)); - } + if (pic1.columns() < 320) + { + pic1.zoom(Magick::Geometry(320, pic1.rows() * 320 / pic1.columns(), 0, 0)); + } - if (pic2.columns() < 320) - { - pic2.zoom(Magick::Geometry(320, pic2.rows() * 320 / pic2.columns(), 0, 0)); - } + if (pic2.columns() < 320) + { + pic2.zoom(Magick::Geometry(320, pic2.rows() * 320 / pic2.columns(), 0, 0)); + } - int width = std::min(pic1.columns(), pic2.columns()); - int height = std::min(pic1.rows(), pic2.rows()); - Magick::Geometry geo1(width, height, pic1.columns()/2 - width/2, pic1.rows()/2 - height/2); - Magick::Geometry geo2(width, height, pic2.columns()/2 - width/2, pic2.rows()/2 - height/2); - pic1.crop(geo1); - pic2.crop(geo2); + int width = std::min(pic1.columns(), pic2.columns()); + int height = std::min(pic1.rows(), pic2.rows()); + Magick::Geometry geo1(width, height, pic1.columns()/2 - width/2, pic1.rows()/2 - height/2); + Magick::Geometry geo2(width, height, pic2.columns()/2 - width/2, pic2.rows()/2 - height/2); + pic1.crop(geo1); + pic2.crop(geo2); - Magick::Image composite(Magick::Geometry(width*2, height, 0, 0), "white"); - composite.draw(Magick::DrawableCompositeImage(0, 0, pic1)); - composite.draw(Magick::DrawableCompositeImage(width, 0, pic2)); - composite.font("@coolvetica.ttf"); + Magick::Image composite(Magick::Geometry(width*2, height, 0, 0), "white"); + composite.draw(Magick::DrawableCompositeImage(0, 0, pic1)); + composite.draw(Magick::DrawableCompositeImage(width, 0, pic2)); + composite.font("@coolvetica.ttf"); - double fontsize = 72; - for (;;) - { - composite.fontPointsize(fontsize); - - Magick::TypeMetric metric; - composite.fontTypeMetrics(ant1, &metric); - if (metric.textWidth() > 300) + double fontsize = 72; + for (;;) { - fontsize -= 0.5; - continue; - } + composite.fontPointsize(fontsize); - composite.fontTypeMetrics(ant2, &metric); - if (metric.textWidth() > 300) - { - fontsize -= 0.5; - continue; - } + Magick::TypeMetric metric; + composite.fontTypeMetrics(ant1, &metric); + if (metric.textWidth() > 300) + { + fontsize -= 0.5; + continue; + } - break; - } - - Magick::TypeMetric metric; - composite.fontTypeMetrics(ant1, &metric); - int y = rand() % ((int)(composite.rows() - 40 - metric.textHeight())) + 20; - y = composite.rows() - y; - int x1 = (width - 40 - metric.textWidth())/2+20; - composite.fontTypeMetrics(ant2, &metric); - int x2 = (width - 40 - metric.textWidth())/2+20+width; - composite.strokeColor("white"); - composite.strokeWidth(2); - composite.antiAlias(false); - composite.draw(Magick::DrawableText(x1, y, ant1)); - composite.draw(Magick::DrawableText(x2, y, ant2)); + composite.fontTypeMetrics(ant2, &metric); + if (metric.textWidth() > 300) + { + fontsize -= 0.5; + continue; + } + + break; + } - composite.magick("png"); + Magick::TypeMetric metric; + composite.fontTypeMetrics(ant1, &metric); + std::uniform_int_distribution rowdist(20, (int)(composite.rows() - 19 - metric.textHeight())); + int y = rowdist(random_engine); + y = composite.rows() - y; + int x1 = (width - 40 - metric.textWidth())/2+20; + composite.fontTypeMetrics(ant2, &metric); + int x2 = (width - 40 - metric.textWidth())/2+20+width; + composite.strokeColor("white"); + composite.strokeWidth(2); + composite.antiAlias(false); + composite.draw(Magick::DrawableText(x1, y, ant1)); + composite.draw(Magick::DrawableText(x2, y, ant2)); - Magick::Blob outputimg; - composite.write(&outputimg); + composite.magick("png"); - std::cout << "Generated image!" << std::endl << "Tweeting..." << std::endl; + Magick::Blob outputimg; + composite.write(&outputimg); - std::stringstream msg; - msg << capitalize(ant1); - msg << " vs. "; - msg << capitalize(ant2); + std::cout << "Generated image!" << std::endl << "Tweeting..." << std::endl; - long media_id; - twitter::response resp = client.uploadMedia("image/png", (const char*) outputimg.data(), outputimg.length(), media_id); - if (resp != twitter::response::ok) + std::stringstream msg; + msg << capitalize(ant1); + msg << " vs. "; + msg << capitalize(ant2); + + long media_id = client.uploadMedia("image/png", (const char*) outputimg.data(), outputimg.length()); + client.updateStatus(msg.str(), {media_id}); + + std::cout << "Done!" << std::endl << "Waiting..." << std::endl << std::endl; + } catch (const curl::curl_easy_exception& error) { - std::cout << "Twitter error while uploading image: " << resp << std::endl; - sleep(delay); - - continue; - } - - twitter::tweet tw; - resp = client.updateStatus(msg.str(), tw, {media_id}); - if (resp != twitter::response::ok) + error.print_traceback(); + } catch (const twitter::twitter_error& e) { - std::cout << "Twitter error while tweeting: " << resp << std::endl; - sleep(delay); - - continue; + std::cout << "Twitter error: " << e.what() << std::endl; } - std::cout << "Done!" << std::endl << "Waiting..." << std::endl << std::endl; - - sleep(delay); + std::this_thread::sleep_for(std::chrono::seconds(delay)); } return 0; diff --git a/vendor/libtwittercpp b/vendor/libtwittercpp index a3d1ed0..a2d28cf 160000 --- a/vendor/libtwittercpp +++ b/vendor/libtwittercpp @@ -1 +1 @@ -Subproject commit a3d1ed08683c75c22d13f25e33f4333debf4f718 +Subproject commit a2d28cfbd7ab8ea71a802f06c2ae76c62decb029 -- cgit 1.4.1