From 59ff7f8821028beb4202e5226f24920f3ae9fe3f Mon Sep 17 00:00:00 2001 From: tastytea Date: Wed, 7 Mar 2018 11:41:16 +0100 Subject: [PATCH] Write mentions to file --- CMakeLists.txt | 2 +- README.md | 26 +++++++++++++++++++-- src/config.cpp | 7 ++++++ src/mastobotmon.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++- src/mastobotmon.hpp | 15 ++++++++----- src/mastodon.cpp | 16 +++++++++++++ 6 files changed, 112 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 028fc6a..53cbcb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.7) project (mastobotmon - VERSION 0.1.4 + VERSION 0.2.0 LANGUAGES CXX) include(GNUInstallDirs) diff --git a/README.md b/README.md index b414f90..8652bbc 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ * Tested OS: Linux * C++ compiler (tested: gcc 6.4, clang 5.0) * [cmake](https://cmake.org/) (tested: 3.9.6) - * [mastodon-cpp](https://github.com/tastytea/mastodon-cpp) (at least: 0.4.4) + * [mastodon-cpp](https://github.com/tastytea/mastodon-cpp) (at least: 0.6.0) * [jsoncpp](https://github.com/open-source-parsers/jsoncpp) (tested: 1.8.1) ## Get sourcecode @@ -48,6 +48,28 @@ Same as [mastodon-cpp](https://github.com/tastytea/mastodon-cpp/blob/master/READ If you use a debug build, you get more verbose error messages. +## Example config file + + { + "accounts" : { + "account1@example.social" : { + "access_token" : "xxxx", + "minutes" : 720 + }, + "account2@example.social" : { + "access_token" : "yyyy", + "minutes" : 1450 + } + }, + "daemon_check" : 10, + "data_dir" : "/home/user/mastobotmon", + "mode" : "cron" + } + +## Mentions + +Mentions are written to `data_dir/mentions_account.csv`. The format is: acct;created_at;content. + # TODO * Version 0.1.0 @@ -56,7 +78,7 @@ If you use a debug build, you get more verbose error messages. * [x] Alert if account seems inactive * Version 0.2.0 * [x] Allow to add accounts later - * [ ] Write mentions to file + * [x] Write mentions to file * Version 0.3.0 * [ ] Respect X-RateLimit header * [ ] Write statistics to file diff --git a/src/config.cpp b/src/config.cpp index de7cb3b..7d6f62e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -67,6 +67,12 @@ const bool read_config(Json::Value &document) cerr << "ERROR: \"daemon_check\" not found\n"; return false; } + + if (!document["data_dir"].isString()) + { + cerr << "ERROR: \"data_dir\" not found\n"; + return false; + } } else { @@ -76,6 +82,7 @@ const bool read_config(Json::Value &document) document["mode"] = "cron"; document["daemon_check"] = 10; + document["data_dir"] = "."; return write_config(document); } diff --git a/src/mastobotmon.cpp b/src/mastobotmon.cpp index 58091d1..b532e21 100644 --- a/src/mastobotmon.cpp +++ b/src/mastobotmon.cpp @@ -23,6 +23,8 @@ #include #include #include // get_time +#include +#include #include #include "version.hpp" #include "mastobotmon.hpp" @@ -33,9 +35,37 @@ using std::cin; using std::string; using std::uint16_t; +const bool write_mentions(const string &filepath, Json::Value &mentions) +{ + const std::regex restrip("<[^>]*>"); + + std::ofstream outfile(filepath, std::ios::app); + if (outfile.is_open()) + { + cout << filepath << '\n'; + string output; + for (auto &mention : mentions) + { + output = mention["status"]["account"]["acct"].asString() + ';'; + output += mention["status"]["created_at"].asString() + ';'; + output += mention["status"]["content"].asString() + '\n'; + output = std::regex_replace(output, restrip, ""); + outfile.write(output.c_str(), output.length()); + } + outfile.close(); + + return true; + } + cout << "NOT OPEN" << '\n'; + cout << filepath << '\n'; + + return false; +} + int main(int argc, char *argv[]) { Json::Value document; + uint16_t mainret = 0; if (!read_config(document)) { return 1; @@ -60,6 +90,10 @@ int main(int argc, char *argv[]) Account *acc = new Account(instance, (*it)["access_token"].asString()); acc->set_useragent("mastobotmon/" + string(global::version)); acc->set_minutes((*it)["minutes"].asUInt()); + if (!(*it)["last_mention"].empty()) + { + acc->set_last_mention_id((*it)["last_mention"].asUInt64()); + } accounts.push_back(*acc); } @@ -121,15 +155,34 @@ int main(int argc, char *argv[]) } cout << std::to_string(minutes) << " minutes.\n"; } + + ret = acc.get_mentions(answer); + if (ret == 0) + { + reader.parse(answer, json); + if (!json.empty()) + { + const std::uint64_t lastid = std::stoull(json[0]["id"].asString()); + const string straccount = acct + "@" + acc.get_instance(); + acc.set_last_mention_id(lastid); + document["accounts"][straccount]["last_mention"] = lastid; + write_mentions(document["data_dir"].asString() + "/mentions_" + straccount + ".csv", json); + } + } } } if (ret != 0) { cerr << "Error: " << ret << '\n'; + mainret = ret; } } } - return 0; + if (!write_config(document)) + { + cerr << "Couldn't write config file\n"; + } + return mainret; } diff --git a/src/mastobotmon.hpp b/src/mastobotmon.hpp index e95b9cd..2830924 100644 --- a/src/mastobotmon.hpp +++ b/src/mastobotmon.hpp @@ -25,20 +25,25 @@ using std::uint16_t; using std::string; -const bool read_config(Json::Value &document); -const string get_access_token(const string &account); -const bool add_account(Json::Value &document); -const bool write_config(Json::Value &document); - class Account : public Mastodon::API { public: explicit Account(const string &instance, const string &access_token); const void set_minutes(uint16_t minutes); const uint16_t get_minutes() const; + const uint16_t get_mentions(string &answer); + const void set_last_mention_id(const std::uint64_t &id); private: uint16_t _minutes; + std::uint64_t _last_mention_id; }; +const bool read_config(Json::Value &document); +const string get_access_token(const string &account); +const bool add_account(Json::Value &document); +const bool write_config(Json::Value &document); + +const bool write_mentions(const string &filepath, Json::Value &mentions); + #endif // mastobotmon_HPP diff --git a/src/mastodon.cpp b/src/mastodon.cpp index ec05167..50cc8e7 100644 --- a/src/mastodon.cpp +++ b/src/mastodon.cpp @@ -30,6 +30,7 @@ using std::uint16_t; Account::Account(const string &instance, const string &access_token) : API(instance, access_token) , _minutes(0) +, _last_mention_id(0) { // } @@ -43,3 +44,18 @@ const uint16_t Account::get_minutes() const { return _minutes; } + +const uint16_t Account::get_mentions(string &answer) +{ + parametermap parameters = + { + { "since_id", { std::to_string(_last_mention_id) } }, + { "exclude_types", { "follow", "favourite", "reblog" } } + }; + return get(v1::notifications, parameters, answer); +} + +const void Account::set_last_mention_id(const std::uint64_t &id) +{ + _last_mention_id = id; +}