summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2025-11-09 15:56:32 -0500
committerStar Rauchenberger <fefferburbia@gmail.com>2025-11-09 15:56:32 -0500
commitb5cc36e1cb8830893ee4baa000f5293e242c1114 (patch)
treea390ebf979b1b3e3e4a546199303de963c8e3c2d
parentb98353cafe47441194345f294b654c28aad3d977 (diff)
downloadinfinite-b5cc36e1cb8830893ee4baa000f5293e242c1114.tar.gz
infinite-b5cc36e1cb8830893ee4baa000f5293e242c1114.tar.bz2
infinite-b5cc36e1cb8830893ee4baa000f5293e242c1114.zip
It now posts to Tumblr! The churn never ends.
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt13
-rw-r--r--infinite.cpp103
m---------vendor/liboauthcpp0
4 files changed, 76 insertions, 43 deletions
diff --git a/.gitmodules b/.gitmodules index 043d581..ffd7927 100644 --- a/.gitmodules +++ b/.gitmodules
@@ -1,3 +1,6 @@
1[submodule "vendor/verbly"] 1[submodule "vendor/verbly"]
2 path = vendor/verbly 2 path = vendor/verbly
3 url = https://git.fourisland.com/verbly 3 url = https://git.fourisland.com/verbly
4[submodule "vendor/liboauthcpp"]
5 path = vendor/liboauthcpp
6 url = https://github.com/sirikata/liboauthcpp.git
diff --git a/CMakeLists.txt b/CMakeLists.txt index d8ec06e..cde46f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -1,18 +1,23 @@
1cmake_minimum_required (VERSION 3.1) 1cmake_minimum_required (VERSION 3.31)
2project (infinite) 2project (infinite)
3 3
4add_subdirectory(vendor/verbly) 4add_subdirectory(vendor/verbly)
5 5
6set(LIBOAUTHCPP_BUILD_DEMOS FALSE)
7add_subdirectory(vendor/liboauthcpp/build EXCLUDE_FROM_ALL)
8include_directories(vendor/liboauthcpp/include)
9
6find_package(PkgConfig) 10find_package(PkgConfig)
11find_package(CURL)
7pkg_check_modules(GraphicsMagick GraphicsMagick++ REQUIRED) 12pkg_check_modules(GraphicsMagick GraphicsMagick++ REQUIRED)
8pkg_check_modules(yaml-cpp yaml-cpp REQUIRED) 13pkg_check_modules(yaml-cpp yaml-cpp REQUIRED)
9pkg_check_modules(mastodonpp mastodonpp REQUIRED)
10 14
11include_directories( 15include_directories(
12 ${GraphicsMagick_INCLUDE_DIRS} 16 ${GraphicsMagick_INCLUDE_DIRS}
13 vendor/verbly/lib 17 vendor/verbly/lib
14 vendor/json 18 vendor/json
15 ${mastodonpp_INCLUDE_DIRS} 19 vendor/liboauthcpp/include
20 ${CURL_INCLUDE_DIRS}
16 ${yaml-cpp_INCLUDE_DIRS}) 21 ${yaml-cpp_INCLUDE_DIRS})
17 22
18link_directories( 23link_directories(
@@ -22,4 +27,4 @@ link_directories(
22add_executable(infinite infinite.cpp color.cpp fractal.cpp matrix3x3.cpp vector3d.cpp tinyxml2.cpp triangle.cpp) 27add_executable(infinite infinite.cpp color.cpp fractal.cpp matrix3x3.cpp vector3d.cpp tinyxml2.cpp triangle.cpp)
23set_property(TARGET infinite PROPERTY CXX_STANDARD 17) 28set_property(TARGET infinite PROPERTY CXX_STANDARD 17)
24set_property(TARGET infinite PROPERTY CXX_STANDARD_REQUIRED ON) 29set_property(TARGET infinite PROPERTY CXX_STANDARD_REQUIRED ON)
25target_link_libraries(infinite ${GraphicsMagick_LIBRARIES} verbly ${yaml-cpp_LIBRARIES} ${mastodonpp_LIBRARIES}) 30target_link_libraries(infinite ${GraphicsMagick_LIBRARIES} verbly ${yaml-cpp_LIBRARIES} curl oauthcpp)
diff --git a/infinite.cpp b/infinite.cpp index 5fcea86..5c8ccbc 100644 --- a/infinite.cpp +++ b/infinite.cpp
@@ -7,11 +7,12 @@
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 <mastodonpp/mastodonpp.hpp>
11#include <json.hpp> 10#include <json.hpp>
12#include <algorithm> 11#include <algorithm>
13#include <chrono> 12#include <chrono>
14#include <thread> 13#include <thread>
14#include <liboauthcpp/liboauthcpp.h>
15#include <curl/curl.h>
15 16
16class fill_blanks { 17class fill_blanks {
17 private: 18 private:
@@ -433,6 +434,63 @@ class fill_blanks {
433 } 434 }
434}; 435};
435 436
437void postToTumblr(std::string post_text, Magick::Image& image, const OAuth::Client& client) {
438 nlohmann::json jsonMedia;
439 jsonMedia["type"] = "image/jpeg";
440 jsonMedia["identifier"] = "some-identifier";
441 jsonMedia["width"] = image.columns();
442 jsonMedia["height"] = image.rows();
443 jsonMedia["alt_text"] = post_text;
444 jsonMedia["caption"] = post_text;
445
446 nlohmann::json contentBlock;
447 contentBlock["type"] = "image";
448 contentBlock["media"] = jsonMedia;
449
450 nlohmann::json postBody;
451 postBody["content"].push_back(contentBlock);
452 postBody["tags"] = "inspiration,flame fractal,generated";
453
454 std::string postText = postBody.dump();
455 std::cout << postText << std::endl;
456
457 Magick::Blob blob;
458 image.write(&blob);
459
460 std::string url = "https://api.tumblr.com/v2/blog/icouldswear/posts";
461
462 std::string oauthHeader = client.getFormattedHttpHeader(OAuth::Http::Post, url, "");
463
464 struct curl_slist* header_list = NULL;
465 header_list = curl_slist_append(header_list, oauthHeader.c_str());
466
467 CURL* easy = curl_easy_init();
468 curl_mime* mime = curl_mime_init(easy);
469 curl_mimepart* json_part = curl_mime_addpart(mime);
470 curl_mime_data(json_part, postText.c_str(), CURL_ZERO_TERMINATED);
471 curl_mime_name(json_part, "json");
472 curl_mime_type(json_part, "application/json");
473
474 curl_mimepart* image_part = curl_mime_addpart(mime);
475 curl_mime_data(image_part, reinterpret_cast<const char*>(blob.data()), blob.length());
476 curl_mime_name(image_part, "some-identifier");
477 curl_mime_type(image_part, "image/jpeg");
478 curl_mime_filename(image_part, "image.jpg");
479
480 curl_easy_setopt(easy, CURLOPT_MIMEPOST, mime);
481 curl_easy_setopt(easy, CURLOPT_HTTPHEADER, header_list);
482 curl_easy_setopt(easy, CURLOPT_URL, url.c_str());
483
484 CURLcode error = curl_easy_perform(easy);
485 if (error != CURLE_OK) {
486 std::cout << curl_easy_strerror(error) << std::endl;
487 }
488
489 curl_easy_cleanup(easy);
490 curl_slist_free_all(header_list);
491 curl_mime_free(mime);
492}
493
436int main(int argc, char** argv) 494int main(int argc, char** argv)
437{ 495{
438 srand(time(NULL)); 496 srand(time(NULL));
@@ -449,10 +507,9 @@ int main(int argc, char** argv)
449 std::string configfile(argv[1]); 507 std::string configfile(argv[1]);
450 YAML::Node config = YAML::LoadFile(configfile); 508 YAML::Node config = YAML::LoadFile(configfile);
451 509
452 mastodonpp::Instance instance{ 510 OAuth::Consumer tumblr_consumer(config["consumer_key"].as<std::string>(), config["consumer_secret"].as<std::string>());
453 config["mastodon_instance"].as<std::string>(), 511 OAuth::Token tumblr_token(config["access_token"].as<std::string>(), config["access_token_secret"].as<std::string>());
454 config["mastodon_token"].as<std::string>()}; 512 OAuth::Client tumblr_client(&tumblr_consumer, &tumblr_token);
455 mastodonpp::Connection connection{instance};
456 513
457 // Parse forms file 514 // Parse forms file
458 std::map<std::string, std::vector<std::string>> groups; 515 std::map<std::string, std::vector<std::string>> groups;
@@ -782,41 +839,9 @@ int main(int argc, char** argv)
782 839
783 std::cout << "Generated image!" << std::endl << "Posting..." << std::endl; 840 std::cout << "Generated image!" << std::endl << "Posting..." << std::endl;
784 841
785 std::string tweetText = action; 842 postToTumblr(action, image, tumblr_client);
786 tweetText.resize(140);
787
788 auto answer{connection.post(mastodonpp::API::v1::media,
789 {{"file", std::string("@file:") + tempfile}, {"description", tweetText}})};
790 if (!answer)
791 {
792 if (answer.curl_error_code == 0)
793 {
794 std::cout << "HTTP status: " << answer.http_status << std::endl;
795 }
796 else
797 {
798 std::cout << "libcurl error " << std::to_string(answer.curl_error_code)
799 << ": " << answer.error_message << std::endl;
800 }
801 } else {
802 nlohmann::json response_json = nlohmann::json::parse(answer.body);
803 answer = connection.post(mastodonpp::API::v1::statuses,
804 {{"status", tweetText}, {"media_ids",
805 std::vector<std::string_view>{response_json["id"].get<std::string>()}}});
806 843
807 if (!answer) 844 std::cout << "Posted!" << std::endl;
808 {
809 if (answer.curl_error_code == 0)
810 {
811 std::cout << "HTTP status: " << answer.http_status << std::endl;
812 }
813 else
814 {
815 std::cout << "libcurl error " << std::to_string(answer.curl_error_code)
816 << ": " << answer.error_message << std::endl;
817 }
818 }
819 }
820 845
821 std::this_thread::sleep_for(std::chrono::hours(12)); 846 std::this_thread::sleep_for(std::chrono::hours(12));
822 } 847 }
diff --git a/vendor/liboauthcpp b/vendor/liboauthcpp new file mode 160000
Subproject 2893f1bf42e1dfd5acf0dd849519cf27ac9c739