Operator
C++ library for plugging into matrix.org
All Classes Namespaces Files Functions Typedefs Pages
liboperator-glib/examples/chathistory.cc
#include "../http.hh"
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <functional>
using namespace Operator;
using json = nlohmann::json;
using namespace std::placeholders;
GMainLoop *loop;
std::string roomid;
void handleMessages(std::shared_ptr<Error::Error> error, const std::string &start, const std::string &end, const std::vector<json> &events, Operator::Client::HTTPClientAPI *pClient, std::vector<std::string> *pMessages, std::vector<std::string>::iterator *pMsg_it) {
Operator::Client::HTTPClientAPI &client = *pClient;
if (error)
{
std::cerr << "Error backfilling: " << error->to_string() << std::endl;
client.logout([](std::shared_ptr<Error::Error> error) {
g_main_loop_quit(loop);
});
}
else
{
std::vector<std::string> &messages = *pMessages;
std::vector<std::string>::iterator &msg_it = *pMsg_it;
for (auto it = events.begin(); msg_it != messages.begin() && it != events.end(); ++it)
{
if ((*it)["type"].get<std::string>() == "m.room.message")
{
--msg_it;
const json &content = (*it)["content"];
if ((*it)["content"]["msgtype"].get<std::string>() == "m.emote")
{
*msg_it = "* " + (*it)["sender"].get<std::string>() + content["body"].get<std::string>();
}
else
{
*msg_it = (*it)["sender"].get<std::string>() + ": " + content["body"].get<std::string>();
}
}
}
if (msg_it != messages.begin() && !events.empty())
{
pClient->roomMessages(roomid, end, "", "b", 0, std::bind(handleMessages, _1, _2, _3, _4, pClient, pMessages, pMsg_it));
}
else
{
for (; msg_it != messages.end(); ++msg_it)
{
std::cout << (*msg_it) << std::endl;
}
pClient->logout([](std::shared_ptr<Error::Error> error) {
if (error)
{
std::cerr << "Error in logout: " << error->to_string() << std::endl;
}
g_main_loop_quit(loop);
});
}
}
}
int main(int argc, char**argv)
{
if (argc != 6 || !strcmp(argv[1], "--help"))
{
std::cout << "Usage:\n";
std::cout << " " << argv[0] << " <homeserver> <username> <password> <roomid> <limit>\n";
exit(0);
}
roomid = argv[4];
SoupSession *session = soup_session_new();
loop = g_main_loop_new(nullptr, FALSE);
Operator::GLib::HTTPAdapter adapter(session);
Operator::Client::HTTPClientAPI client(adapter, argv[1]);
std::vector<std::string> messages(atoi(argv[5]));
auto msg_it = messages.end();
client.login(argv[2], argv[3], [&client, &messages, &msg_it](std::shared_ptr<Error::Error> error, const std::string &username, const std::string &homeserver) {
if (error)
{
std::cerr << "Error in login: " << error->to_string() << std::endl;
g_main_loop_quit(loop);
}
else
{
// FIXME: add a filter to only send events from one room, and only send
// message events
client.sync("", "", false, "offline", 0, [&client, &messages, &msg_it](std::shared_ptr<Error::Error> error, const std::string &next, json rooms, json presence) {
if (error)
{
std::cerr << "Error in sync: " << error->to_string() << std::endl;
client.logout([](std::shared_ptr<Error::Error> error) {
g_main_loop_quit(loop);
});
}
else
{
json &timeline = rooms["join"][roomid]["timeline"];
json &events = timeline["events"];
for (auto it = events.end(); msg_it != messages.begin() && it != events.begin(); --it)
{
json::iterator prev = it; --prev;
if ((*prev)["type"].get<std::string>() == "m.room.message")
{
--msg_it;
json &content = (*prev)["content"];
if ((*prev)["content"]["msgtype"].get<std::string>() == "m.emote")
{
*msg_it = "* " + (*prev)["sender"].get<std::string>() + content["body"].get<std::string>();
}
else
{
*msg_it = (*prev)["sender"].get<std::string>() + ": " + content["body"].get<std::string>();
}
}
}
std::cerr << "[done copying]\n";
if (msg_it != messages.begin() && timeline["limited"].get<bool>())
{
std::cerr << "[Backfilling]\n";
client.roomMessages(roomid, timeline["prev_batch"], "", "b", 0, std::bind(handleMessages, _1, _2, _3, _4, &client, &messages, &msg_it));
}
else
{
for (; msg_it != messages.end(); ++msg_it)
{
std::cout << (*msg_it) << std::endl;
}
client.logout([](std::shared_ptr<Error::Error> error) {
if (error)
{
std::cerr << "Error in logout: " << error->to_string() << std::endl;
}
g_main_loop_quit(loop);
});
}
}
});
}
});
g_main_loop_run(loop);
}