diff options
| author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-11-27 15:18:05 -0500 |
|---|---|---|
| committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2016-11-27 15:18:05 -0500 |
| commit | 5413c1c0dc40b24fd0932e3b8f7fdfa3a596859f (patch) | |
| tree | e94f18b60816cb409ec5043a38a65c0a0da6a93d | |
| parent | 3944d738d8d5eb0f82dfa3b24be2d9de3eb484c9 (diff) | |
| download | infinite-5413c1c0dc40b24fd0932e3b8f7fdfa3a596859f.tar.gz infinite-5413c1c0dc40b24fd0932e3b8f7fdfa3a596859f.tar.bz2 infinite-5413c1c0dc40b24fd0932e3b8f7fdfa3a596859f.zip | |
Updated verbly & libtwitter++ to remove dependence on json submodule
The current version of libtwitter++ has an updated API, so the bot had to be updated to use the new API; additionally, the usage of the UNIX-dependent sleep call was replaced by the sleep functionality in the C++ standard library. At some point, we should also replace the usage of the C random library with the C++ random library. Finally, some initialization functionality that was being repeated for every generated tweet was instead moved out of the main loop.
| -rw-r--r-- | infinite.cpp | 124 | ||||
| m--------- | vendor/libtwittercpp | 0 | ||||
| m--------- | vendor/verbly | 0 |
3 files changed, 54 insertions, 70 deletions
| diff --git a/infinite.cpp b/infinite.cpp index 501dddc..a491302 100644 --- a/infinite.cpp +++ b/infinite.cpp | |||
| @@ -7,9 +7,10 @@ | |||
| 7 | #include <fstream> | 7 | #include <fstream> |
| 8 | #include <dirent.h> | 8 | #include <dirent.h> |
| 9 | #include <yaml-cpp/yaml.h> | 9 | #include <yaml-cpp/yaml.h> |
| 10 | #include <unistd.h> | ||
| 11 | #include <twitter.h> | 10 | #include <twitter.h> |
| 12 | #include <algorithm> | 11 | #include <algorithm> |
| 12 | #include <chrono> | ||
| 13 | #include <thread> | ||
| 13 | 14 | ||
| 14 | class fill_blanks { | 15 | class fill_blanks { |
| 15 | private: | 16 | private: |
| @@ -438,8 +439,6 @@ int main(int argc, char** argv) | |||
| 438 | 439 | ||
| 439 | Magick::InitializeMagick(nullptr); | 440 | Magick::InitializeMagick(nullptr); |
| 440 | 441 | ||
| 441 | int delay = 60 * 60; | ||
| 442 | |||
| 443 | YAML::Node config = YAML::LoadFile("config.yml"); | 442 | YAML::Node config = YAML::LoadFile("config.yml"); |
| 444 | twitter::auth auth; | 443 | twitter::auth auth; |
| 445 | auth.setConsumerKey(config["consumer_key"].as<std::string>()); | 444 | auth.setConsumerKey(config["consumer_key"].as<std::string>()); |
| @@ -449,18 +448,16 @@ int main(int argc, char** argv) | |||
| 449 | 448 | ||
| 450 | twitter::client client(auth); | 449 | twitter::client client(auth); |
| 451 | 450 | ||
| 452 | for (;;) | 451 | // Parse forms file |
| 452 | std::map<std::string, std::vector<std::string>> groups; | ||
| 453 | { | 453 | { |
| 454 | std::cout << "Generating text..." << std::endl; | ||
| 455 | |||
| 456 | std::map<std::string, std::vector<std::string>> groups; | ||
| 457 | std::ifstream datafile("forms.txt"); | 454 | std::ifstream datafile("forms.txt"); |
| 458 | if (!datafile.is_open()) | 455 | if (!datafile.is_open()) |
| 459 | { | 456 | { |
| 460 | std::cout << "Could not find forms.txt" << std::endl; | 457 | std::cout << "Could not find forms.txt" << std::endl; |
| 461 | return 1; | 458 | return 1; |
| 462 | } | 459 | } |
| 463 | 460 | ||
| 464 | bool newgroup = true; | 461 | bool newgroup = true; |
| 465 | std::string line; | 462 | std::string line; |
| 466 | std::string curgroup; | 463 | std::string curgroup; |
| @@ -470,7 +467,7 @@ int main(int argc, char** argv) | |||
| 470 | { | 467 | { |
| 471 | line.pop_back(); | 468 | line.pop_back(); |
| 472 | } | 469 | } |
| 473 | 470 | ||
| 474 | if (newgroup) | 471 | if (newgroup) |
| 475 | { | 472 | { |
| 476 | curgroup = line; | 473 | curgroup = line; |
| @@ -484,10 +481,38 @@ int main(int argc, char** argv) | |||
| 484 | } | 481 | } |
| 485 | } | 482 | } |
| 486 | } | 483 | } |
| 484 | } | ||
| 487 | 485 | ||
| 488 | datafile.close(); | 486 | // Read in fonts |
| 487 | std::vector<std::string> fonts; | ||
| 488 | { | ||
| 489 | DIR* fontdir; | ||
| 490 | struct dirent* ent; | ||
| 491 | if ((fontdir = opendir("fonts")) == nullptr) | ||
| 492 | { | ||
| 493 | std::cout << "Couldn't find fonts." << std::endl; | ||
| 494 | return -1; | ||
| 495 | } | ||
| 496 | |||
| 497 | while ((ent = readdir(fontdir)) != nullptr) | ||
| 498 | { | ||
| 499 | std::string dname(ent->d_name); | ||
| 500 | if ((dname.find(".otf") != std::string::npos) || (dname.find(".ttf") != std::string::npos)) | ||
| 501 | { | ||
| 502 | fonts.push_back(dname); | ||
| 503 | } | ||
| 504 | } | ||
| 505 | |||
| 506 | closedir(fontdir); | ||
| 507 | } | ||
| 508 | |||
| 509 | verbly::data database {"data.sqlite3"}; | ||
| 489 | 510 | ||
| 490 | verbly::data database {"data.sqlite3"}; | 511 | for (;;) |
| 512 | { | ||
| 513 | // Generate the text | ||
| 514 | std::cout << "Generating text..." << std::endl; | ||
| 515 | |||
| 491 | std::string action = "{FORM}"; | 516 | std::string action = "{FORM}"; |
| 492 | int tknloc; | 517 | int tknloc; |
| 493 | while ((tknloc = action.find("{")) != std::string::npos) | 518 | while ((tknloc = action.find("{")) != std::string::npos) |
| @@ -503,12 +528,6 @@ int main(int argc, char** argv) | |||
| 503 | if (canontkn == "NOUN") | 528 | if (canontkn == "NOUN") |
| 504 | { | 529 | { |
| 505 | result = database.nouns().is_not_proper().random().limit(1).with_complexity(1).run().front().singular_form(); | 530 | result = database.nouns().is_not_proper().random().limit(1).with_complexity(1).run().front().singular_form(); |
| 506 | // } else if (canontkn == "PLURAL_NOUN") | ||
| 507 | // { | ||
| 508 | // result = database.nouns().is_not_proper().requires_plural_form().random().limit(1).with_complexity(1).run().front().plural_form(); | ||
| 509 | // } else if (canontkn == "ADJECTIVE") | ||
| 510 | // { | ||
| 511 | // result = database.adjectives().with_complexity(1).random().limit(1).run().front().base_form(); | ||
| 512 | } else if (canontkn == "SUPERLATIVE") | 531 | } else if (canontkn == "SUPERLATIVE") |
| 513 | { | 532 | { |
| 514 | result = database.adjectives().requires_superlative_form().random().limit(1).run().front().superlative_form(); | 533 | result = database.adjectives().requires_superlative_form().random().limit(1).run().front().superlative_form(); |
| @@ -578,21 +597,23 @@ int main(int argc, char** argv) | |||
| 578 | 597 | ||
| 579 | action.replace(tknloc, action.find("}")-tknloc+1, finalresult); | 598 | action.replace(tknloc, action.find("}")-tknloc+1, finalresult); |
| 580 | } | 599 | } |
| 581 | 600 | ||
| 582 | std::cout << action << std::endl; | 601 | std::cout << action << std::endl; |
| 583 | 602 | ||
| 603 | // Generate the fractal | ||
| 584 | double zoom = 2.0; | 604 | double zoom = 2.0; |
| 585 | double target_w = 1280; | 605 | double target_w = 1280; |
| 586 | double target_h = 800; | 606 | double target_h = 800; |
| 587 | double sample_rate = 3; | 607 | double sample_rate = 3; |
| 588 | |||
| 589 | std::cout << "Generating flame fractal..." << std::endl; | ||
| 590 | 608 | ||
| 591 | Magick::Image image(Magick::Geometry(target_w, target_h), "black"); | 609 | Magick::Image image(Magick::Geometry(target_w, target_h), "black"); |
| 592 | image.type(Magick::TrueColorMatteType); | 610 | image.type(Magick::TrueColorMatteType); |
| 593 | 611 | ||
| 594 | for (;;) | 612 | double coverage = 0.0; |
| 613 | while (coverage < 0.05) | ||
| 595 | { | 614 | { |
| 615 | std::cout << "Generating flame fractal..." << std::endl; | ||
| 616 | |||
| 596 | Fractal fractal = Fractal::random(); | 617 | Fractal fractal = Fractal::random(); |
| 597 | std::vector<Color> irradiance(target_w*target_h*sample_rate*sample_rate, Color(0.0, 0.0, 0.0, 0.0)); | 618 | std::vector<Color> irradiance(target_w*target_h*sample_rate*sample_rate, Color(0.0, 0.0, 0.0, 0.0)); |
| 598 | 619 | ||
| @@ -700,39 +721,13 @@ int main(int argc, char** argv) | |||
| 700 | } | 721 | } |
| 701 | } | 722 | } |
| 702 | 723 | ||
| 703 | double coverage = ((double)covered/(double)(target_w*target_h)); | 724 | coverage = ((double)covered/(double)(target_w*target_h)); |
| 704 | std::cout << coverage << " coverage" << std::endl; | 725 | std::cout << coverage << " coverage" << std::endl; |
| 705 | 726 | ||
| 706 | view.sync(); | 727 | view.sync(); |
| 707 | |||
| 708 | if (coverage >= 0.05) | ||
| 709 | { | ||
| 710 | break; | ||
| 711 | } | ||
| 712 | |||
| 713 | std::cout << "Regenerating..." << std::endl; | ||
| 714 | } | ||
| 715 | |||
| 716 | DIR* fontdir; | ||
| 717 | struct dirent* ent; | ||
| 718 | if ((fontdir = opendir("fonts")) == nullptr) | ||
| 719 | { | ||
| 720 | std::cout << "Couldn't find fonts." << std::endl; | ||
| 721 | return -1; | ||
| 722 | } | 728 | } |
| 723 | |||
| 724 | std::vector<std::string> fonts; | ||
| 725 | while ((ent = readdir(fontdir)) != nullptr) | ||
| 726 | { | ||
| 727 | std::string dname(ent->d_name); | ||
| 728 | if ((dname.find(".otf") != std::string::npos) || (dname.find(".ttf") != std::string::npos)) | ||
| 729 | { | ||
| 730 | fonts.push_back(dname); | ||
| 731 | } | ||
| 732 | } | ||
| 733 | |||
| 734 | closedir(fontdir); | ||
| 735 | 729 | ||
| 730 | // Put text on top of the fractal | ||
| 736 | std::string subaction = action; | 731 | std::string subaction = action; |
| 737 | std::string font = fonts[rand() % fonts.size()]; | 732 | std::string font = fonts[rand() % fonts.size()]; |
| 738 | if (font == "Le_Super_Type_SemiBold.ttf") | 733 | if (font == "Le_Super_Type_SemiBold.ttf") |
| @@ -779,16 +774,6 @@ int main(int argc, char** argv) | |||
| 779 | 774 | ||
| 780 | std::cout << "Generated image!" << std::endl << "Tweeting..." << std::endl; | 775 | std::cout << "Generated image!" << std::endl << "Tweeting..." << std::endl; |
| 781 | 776 | ||
| 782 | long media_id; | ||
| 783 | twitter::response resp = client.uploadMedia("image/jpeg", (const char*) outputimg.data(), outputimg.length(), media_id); | ||
| 784 | if (resp != twitter::response::ok) | ||
| 785 | { | ||
| 786 | std::cout << "Twitter error while uploading image: " << resp << std::endl; | ||
| 787 | sleep(delay); | ||
| 788 | |||
| 789 | continue; | ||
| 790 | } | ||
| 791 | |||
| 792 | std::string tweetText; | 777 | std::string tweetText; |
| 793 | size_t tweetLim = 140 - client.getConfiguration().getCharactersReservedPerMedia() - client.getUser().getScreenName().length() - 6; | 778 | size_t tweetLim = 140 - client.getConfiguration().getCharactersReservedPerMedia() - client.getUser().getScreenName().length() - 6; |
| 794 | if (action.length() > tweetLim) | 779 | if (action.length() > tweetLim) |
| @@ -798,18 +783,17 @@ int main(int argc, char** argv) | |||
| 798 | tweetText = "\"" + action + "\" --@" + client.getUser().getScreenName(); | 783 | tweetText = "\"" + action + "\" --@" + client.getUser().getScreenName(); |
| 799 | } | 784 | } |
| 800 | 785 | ||
| 801 | twitter::tweet tw; | 786 | try |
| 802 | resp = client.updateStatus(tweetText, tw, twitter::tweet(), {media_id}); | ||
| 803 | if (resp != twitter::response::ok) | ||
| 804 | { | 787 | { |
| 805 | std::cout << "Twitter error while tweeting: " << resp << std::endl; | 788 | long media_id = client.uploadMedia("image/jpeg", (const char*) outputimg.data(), outputimg.length()); |
| 806 | sleep(delay); | 789 | client.updateStatus(tweetText, {media_id}); |
| 807 | 790 | ||
| 808 | continue; | 791 | std::cout << "Done!" << std::endl << "Waiting..." << std::endl << std::endl; |
| 792 | } catch (const twitter::twitter_error& e) | ||
| 793 | { | ||
| 794 | std::cout << "Twitter error: " << e.what() << std::endl; | ||
| 809 | } | 795 | } |
| 810 | 796 | ||
| 811 | std::cout << "Done!" << std::endl << "Waiting..." << std::endl << std::endl; | 797 | std::this_thread::sleep_for(std::chrono::hours(1)); |
| 812 | |||
| 813 | sleep(delay); | ||
| 814 | } | 798 | } |
| 815 | } | 799 | } |
| diff --git a/vendor/libtwittercpp b/vendor/libtwittercpp | |||
| Subproject aceb3cc33ee78cce1077252aff8a8808a3195ff | Subproject d90a1e74c77ba67f25a812609fd49d479bc464d | ||
| diff --git a/vendor/verbly b/vendor/verbly | |||
| Subproject 6c2aca03c89b37e136ab4c7ea58b485dadc85bc | Subproject 1f898f3bd66c29672275c2c884b17ba662ced62 | ||
