feiertagebot/feiertagebot.cpp

229 lines
6.2 KiB
C++
Raw Normal View History

2019-02-11 19:15:37 +01:00
// Author: tastytea <tastytea@tastytea.de>
// CC-0 / Public Domain
2019-02-11 21:32:44 +01:00
2020-05-16 17:43:36 +02:00
#include "xdgjson/src/xdgjson.hpp"
#include <mastodonpp/mastodonpp.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Exception.hpp>
#include <curlpp/Infos.hpp>
#include <json/json.h>
2019-02-11 21:32:44 +01:00
#include <string>
2020-05-16 17:43:36 +02:00
#include <string_view>
2019-02-11 21:32:44 +01:00
#include <exception>
#include <iostream>
#include <sstream>
2019-02-12 01:46:48 +01:00
#include <vector>
#include <algorithm>
#include <map>
#include <chrono>
#include <ctime>
#include <cstdint>
2019-02-11 21:32:44 +01:00
namespace curlopts = curlpp::options;
using std::string;
using std::cout;
using std::cerr;
using std::endl;
2019-02-12 01:46:48 +01:00
using std::vector;
using std::chrono::system_clock;
using std::chrono::hours;
2020-05-16 17:43:36 +02:00
using std::string_view;
2019-02-12 01:46:48 +01:00
2020-05-16 17:43:36 +02:00
constexpr string_view version = "2020-05-16_1";
2019-02-12 01:46:48 +01:00
2020-05-16 17:43:36 +02:00
struct holiday
2019-02-12 01:46:48 +01:00
{
string date;
string description;
vector<string> regions;
};
2020-05-16 17:43:36 +02:00
string decode_state(const string &abbr)
2019-02-12 01:46:48 +01:00
{
const std::map<string, string> states =
{
{ "BW", "Baden-Württemberg" },
{ "BY", "Bayern" },
{ "BE", "Berlin" },
{ "BB", "Brandenburg" },
{ "HB", "Bremen" },
{ "HH", "Hamburg" },
{ "HE", "Hessen" },
{ "MV", "Mecklenburg-Vorpommern" },
{ "NI", "Niedersachsen" },
{ "NW", "Nordrhein-Westfalen" },
{ "RP", "Rheinland-Pfalz" },
{ "SL", "Saarland" },
{ "SN", "Sachsen" },
{ "ST", "Sachsen-Anhalt" },
{ "SH", "Schleswig-Holstein" },
{ "TH", "Thüringen" }
};
if (states.find(abbr) != states.end())
{
return states.find(abbr)->second;
}
2020-05-16 17:43:36 +02:00
return abbr;
2019-02-12 01:46:48 +01:00
}
2020-05-16 17:43:36 +02:00
string get_date(const system_clock::time_point &timepoint,
const string &format)
2019-02-12 01:46:48 +01:00
{
std::time_t time = system_clock::to_time_t(timepoint);
std::tm *timeinfo = std::localtime(&time);
char buffer[1024];
std::strftime(buffer, 1024, format.c_str(), timeinfo);
return string(buffer);
}
2020-05-16 17:43:36 +02:00
string get_token(const string &instance)
2019-02-12 01:46:48 +01:00
{
mastodonpp::Instance server{instance, ""};
mastodonpp::Instance::ObtainToken token{server};
auto answer{token.step_1("feiertagebot",
"write:statuses",
"https://schlomp.space/tastytea/feiertagebot")};
if (!answer)
2019-02-12 01:46:48 +01:00
{
cerr << "Error " << answer.error_message << endl;
2019-02-12 01:46:48 +01:00
return "";
}
string code;
cout << "Visit " << answer << " to authorize this application.\n";
2019-02-12 01:46:48 +01:00
cout << "Insert code: ";
std::getline(std::cin, code);
answer = token.step_2(code);
if (!answer)
2019-02-12 01:46:48 +01:00
{
cerr << "Error " << answer.error_message << endl;
2019-02-12 01:46:48 +01:00
return "";
}
return answer.body;
2019-02-12 01:46:48 +01:00
}
2019-02-11 19:15:37 +01:00
int main()
{
2020-05-16 17:43:36 +02:00
string instance;
string access_token;
2019-02-12 01:46:48 +01:00
xdgjson config("feiertagebot.json");
config.read();
Json::Value &json = config.get_json();
if (json["instance"].isString())
{
instance = json["instance"].asString();
}
else
{
cout << "Instance domain: ";
std::getline(std::cin, instance);
json["instance"] = instance;
}
if (json["access_token"].isString())
{
access_token = json["access_token"].asString();
}
else
{
access_token = get_token(instance);
json["access_token"] = access_token;
config.write();
}
2019-02-11 21:32:44 +01:00
try
{
2019-02-12 01:46:48 +01:00
string year = get_date(system_clock::now(), "%Y");
2019-04-18 18:44:12 +02:00
string tomorrow = get_date(system_clock::now() + hours(24), "%Y-%m-%d");
string overmorrow = get_date(system_clock::now() + hours(48),
"%Y-%m-%d");
2019-02-12 02:17:55 +01:00
2019-02-11 21:32:44 +01:00
curlpp::Easy request;
std::stringstream ss;
request.setOpt<curlopts::Url>("https://feiertage-api.de/api/?jahr="
+ year);
2020-05-16 17:43:36 +02:00
request.setOpt<curlopts::UserAgent>(string("feiertagebot/") += version);
2019-02-11 21:32:44 +01:00
request.setOpt<curlopts::FollowLocation>(true);
ss << request;
Json::Value root;
ss >> root;
2019-02-12 01:46:48 +01:00
string output;
for (const string &date : { tomorrow, overmorrow })
2019-02-11 21:32:44 +01:00
{
2020-05-16 17:43:36 +02:00
holiday current_day;
for (Json::Value::const_iterator it_root = root.begin();
it_root != root.end(); ++it_root)
2019-02-12 01:46:48 +01:00
{
for (Json::Value::const_iterator it_region = it_root->begin();
it_region != it_root->end(); ++it_region)
2019-02-12 01:46:48 +01:00
{
if ((*it_region)["datum"] == date)
{
current_day.date = date;
current_day.description = it_region.key().asString();
current_day.regions.push_back(it_root.key().asString());
}
}
}
if (current_day.date.empty())
{
continue;
}
output += "Am " + current_day.date + " ist "
+ current_day.description + ", ein gesetzlicher Feiertag in ";
if (std::find(current_day.regions.begin(),
current_day.regions.end(), "NATIONAL")
!= current_day.regions.end())
2019-02-12 01:46:48 +01:00
{
output += "Deutschland.\n\n";
2019-02-12 01:46:48 +01:00
}
else
2019-02-11 21:32:44 +01:00
{
2019-02-12 01:46:48 +01:00
bool firstrun = true;
for (const string &region : current_day.regions)
2019-02-11 21:32:44 +01:00
{
2019-02-12 01:46:48 +01:00
if (!firstrun)
{
output += ", ";
}
else
{
firstrun = false;
}
output += decode_state(region);
2019-02-11 21:32:44 +01:00
}
output += ".\n\n";
2019-02-12 01:46:48 +01:00
}
}
if (!output.empty())
{
mastodonpp::Instance server{instance, access_token};
mastodonpp::Connection connection{server};
string status{output + "#bot"};
const auto answer{connection.post(mastodonpp::API::v1::statuses,
{{"status", output}})};
if (!answer)
2019-02-12 01:46:48 +01:00
{
cerr << "Error " << answer.error_message << endl;
return answer.curl_error_code;
2019-02-11 21:32:44 +01:00
}
}
}
catch (const std::exception &e)
{
cerr << e.what() << endl;
return 1;
}
2019-02-12 01:46:48 +01:00
2019-02-11 19:15:37 +01:00
return 0;
}