2018-01-15 00:08:14 +01:00
|
|
|
|
/* This file is part of mastodon-cpp.
|
|
|
|
|
* Prints the new toots under a hashtag, designed to be used in cronjobs
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <regex>
|
|
|
|
|
#include <cstdlib>
|
2018-03-18 14:53:51 +01:00
|
|
|
|
#include <fstream>
|
2018-03-18 17:34:44 +01:00
|
|
|
|
#include <sstream>
|
2018-03-18 14:53:51 +01:00
|
|
|
|
#include <jsoncpp/json/json.h>
|
2018-03-21 20:12:45 +01:00
|
|
|
|
#ifdef MASTODON_CPP
|
|
|
|
|
#include "mastodon-cpp.hpp"
|
|
|
|
|
#else
|
|
|
|
|
#include <mastodon-cpp/mastodon-cpp.hpp>
|
|
|
|
|
#endif
|
2018-01-15 00:08:14 +01:00
|
|
|
|
|
|
|
|
|
using Mastodon::API;
|
|
|
|
|
using std::cout;
|
|
|
|
|
using std::string;
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
string limit = "20";
|
|
|
|
|
if (argc < 3)
|
|
|
|
|
{
|
|
|
|
|
std::cerr << "usage: " << argv[0] << " <instance> <hashtag> [limit]\n";
|
|
|
|
|
std::cerr << " Default limit is 20, max limit is 40.\n";
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if (argc == 4)
|
|
|
|
|
{
|
|
|
|
|
limit = argv[3];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mastodon::API masto(argv[1], "");
|
|
|
|
|
string hashtag = argv[2];
|
|
|
|
|
string answer;
|
2018-03-18 17:34:44 +01:00
|
|
|
|
std::stringstream ss;
|
2018-01-15 00:08:14 +01:00
|
|
|
|
std::uint16_t ret;
|
2018-03-18 14:53:51 +01:00
|
|
|
|
Json::Value config;
|
2018-01-15 00:08:14 +01:00
|
|
|
|
string lastid = "0";
|
|
|
|
|
string filename = string(getenv("HOME")) + "/.config/mastocron.json";
|
|
|
|
|
|
|
|
|
|
// Read config file, get last seen toot-id
|
|
|
|
|
try {
|
2018-03-18 14:53:51 +01:00
|
|
|
|
std::ifstream file(filename, std::ifstream::binary);
|
|
|
|
|
file >> config;
|
|
|
|
|
lastid = config.get(hashtag, "0").asString();
|
2018-01-15 00:08:14 +01:00
|
|
|
|
}
|
|
|
|
|
catch (std::exception &e)
|
|
|
|
|
{
|
|
|
|
|
// most likely no config file found, ignore
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only get toots we haven't seen yet
|
2018-01-15 20:23:21 +01:00
|
|
|
|
API::parametermap params =
|
|
|
|
|
{
|
2018-04-19 00:36:39 +02:00
|
|
|
|
{ "hashtag", { hashtag } },
|
2018-01-15 20:23:21 +01:00
|
|
|
|
{ "limit", { limit } },
|
|
|
|
|
{ "since_id", { lastid } }
|
|
|
|
|
};
|
2018-04-19 00:36:39 +02:00
|
|
|
|
ret = masto.get(API::v1::timelines_tag_hashtag, params, answer);
|
2018-01-15 00:08:14 +01:00
|
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
|
{
|
|
|
|
|
// If answer is empty, there are no new toots,
|
|
|
|
|
// if answer is "[]" there are none at all
|
|
|
|
|
if (answer != "" && answer != "[]")
|
|
|
|
|
{
|
2018-01-15 15:34:18 +01:00
|
|
|
|
string ornament = " +++++";
|
|
|
|
|
for (std::uint8_t i = hashtag.size(); i > 0; --i)
|
|
|
|
|
{
|
|
|
|
|
ornament += "+";
|
|
|
|
|
}
|
|
|
|
|
cout << ornament << '\n';
|
|
|
|
|
cout << " + " << hashtag << ": +\n";
|
|
|
|
|
cout << ornament << '\n';
|
|
|
|
|
|
2018-03-18 14:53:51 +01:00
|
|
|
|
Json::Value tree;
|
2018-03-18 17:34:44 +01:00
|
|
|
|
ss.str(answer);
|
|
|
|
|
ss >> tree;
|
2018-01-15 00:08:14 +01:00
|
|
|
|
|
2018-03-18 14:53:51 +01:00
|
|
|
|
for (const auto &toot : tree)
|
2018-01-15 00:08:14 +01:00
|
|
|
|
{
|
2018-03-18 14:53:51 +01:00
|
|
|
|
string content = toot["content"].asString();
|
2018-01-15 00:08:14 +01:00
|
|
|
|
std::regex reparagraph("</p><p>");
|
|
|
|
|
std::regex restrip("<[^>]*>");
|
|
|
|
|
|
|
|
|
|
cout << "++++++++\n";
|
|
|
|
|
content = std::regex_replace(content, reparagraph, "\n\n");
|
|
|
|
|
cout << std::regex_replace(content, restrip, "") << '\n';
|
|
|
|
|
cout << " – ";
|
2018-03-18 14:53:51 +01:00
|
|
|
|
cout << toot["account"]["display_name"].asString()
|
|
|
|
|
<< " (" << toot["account"]["acct"] << ") at "
|
|
|
|
|
<< toot["created_at"].asString() << "\n";
|
|
|
|
|
cout << " " << toot["url"].asString() << '\n';
|
|
|
|
|
for (const auto &media : toot["media_attachments"])
|
2018-01-15 15:34:18 +01:00
|
|
|
|
{
|
2018-03-18 14:53:51 +01:00
|
|
|
|
cout << "Attachment: <" << media["url"].asString() << ">\n";
|
2018-01-15 15:34:18 +01:00
|
|
|
|
}
|
2018-01-15 00:08:14 +01:00
|
|
|
|
cout << "++++++++\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write the id of the newest toot in the config file
|
2018-03-18 14:53:51 +01:00
|
|
|
|
lastid = tree[0]["id"].asString();
|
|
|
|
|
config[hashtag] = lastid;
|
|
|
|
|
|
2018-03-18 17:34:44 +01:00
|
|
|
|
Json::StreamWriterBuilder wbuilder;
|
|
|
|
|
const string output = Json::writeString(wbuilder, config);
|
2018-03-18 14:53:51 +01:00
|
|
|
|
std::ofstream outfile(filename);
|
|
|
|
|
if (outfile.is_open())
|
|
|
|
|
{
|
|
|
|
|
outfile.write(output.c_str(), output.length());
|
|
|
|
|
outfile.close();
|
|
|
|
|
}
|
2018-01-15 00:08:14 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-28 22:37:30 +01:00
|
|
|
|
else if (ret == 13)
|
2018-02-17 20:01:51 +01:00
|
|
|
|
{
|
|
|
|
|
std::cerr << "The URL has permanently changed.\n" <<
|
|
|
|
|
"New URL: " << answer << '\n';
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2018-01-15 00:08:14 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
std::cerr << "Error code: " << ret << '\n';
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|