summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/database/database.cpp10
-rw-r--r--src/xmpp/biboumi_component.cpp79
-rw-r--r--src/xmpp/biboumi_component.hpp10
3 files changed, 93 insertions, 6 deletions
diff --git a/src/database/database.cpp b/src/database/database.cpp
index 009ff0e..be0da8e 100644
--- a/src/database/database.cpp
+++ b/src/database/database.cpp
@@ -138,13 +138,13 @@ void Database::store_muc_message(const std::string& owner, const Iid& iid,
std::vector<db::MucLogLine> Database::get_muc_logs(const std::string& owner, const std::string& chan_name, const std::string& server, int limit)
{
- if (limit < 0)
- limit = 0;
- auto res = litesql::select<db::MucLogLine>(*Database::db,
+ if (limit == -1)
+ limit = 1024;
+ const auto& res = litesql::select<db::MucLogLine>(*Database::db,
db::MucLogLine::Owner == owner &&
db::MucLogLine::IrcChanName == chan_name &&
- db::MucLogLine::IrcServerName == server).orderBy(db::MucLogLine::Date, false).limit(limit).all();
- return {res.rbegin(), res.rend()};
+ db::MucLogLine::IrcServerName == server).orderBy(db::MucLogLine::Id, false).limit(limit).all();
+ return {res.crbegin(), res.crend()};
}
void Database::close()
diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp
index 9acccdb..a49f52e 100644
--- a/src/xmpp/biboumi_component.cpp
+++ b/src/xmpp/biboumi_component.cpp
@@ -8,8 +8,9 @@
#include <xmpp/biboumi_adhoc_commands.hpp>
#include <bridge/list_element.hpp>
#include <config/config.hpp>
-#include <xmpp/jid.hpp>
#include <utils/sha1.hpp>
+#include <utils/time.hpp>
+#include <xmpp/jid.hpp>
#include <stdexcept>
#include <iostream>
@@ -25,6 +26,8 @@
# include <systemd/sd-daemon.h>
#endif
+#include <database/database.hpp>
+
using namespace std::string_literals;
static std::set<std::string> kickable_errors{
@@ -383,6 +386,13 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
this->send_stanza(response);
stanza_error.disable();
}
+#ifdef USE_DATABASE
+ else if ((query = stanza.get_child("query", MAM_NS)))
+ {
+ if (this->handle_mam_request(stanza))
+ stanza_error.disable();
+ }
+#endif
}
else if (type == "get")
{
@@ -525,6 +535,73 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
error_name = "feature-not-implemented";
}
+#ifdef USE_DATABASE
+bool BiboumiComponent::handle_mam_request(const Stanza& stanza)
+{
+ std::string id = stanza.get_tag("id");
+ Jid from(stanza.get_tag("from"));
+ Jid to(stanza.get_tag("to"));
+
+ const XmlNode* query = stanza.get_child("query", MAM_NS);
+ std::string query_id;
+ if (query)
+ query_id = query->get_tag("queryid");
+
+ Iid iid(to.local, {'#', '&'});
+ if (iid.type == Iid::Type::Channel && to.resource.empty())
+ {
+ const auto lines = Database::get_muc_logs(from.bare(), iid.get_local(), iid.get_server(), -1);
+ for (const db::MucLogLine& line: lines)
+ {
+ const auto queryid = query->get_tag("queryid");
+ if (!line.nick.value().empty())
+ this->send_archived_message(line, to.full(), from.full(), queryid);
+ }
+ this->send_iq_result_full_jid(id, from.full(), to.full());
+ return true;
+ }
+ return false;
+}
+
+void BiboumiComponent::send_archived_message(const db::MucLogLine& log_line, const std::string& from, const std::string& to,
+ const std::string& queryid)
+{
+ Stanza message("message");
+ message["from"] = from;
+ message["to"] = to;
+
+ XmlNode result("result");
+ result["xmlns"] = MAM_NS;
+ result["queryid"] = queryid;
+ result["id"] = log_line.uuid.value();
+
+ XmlNode forwarded("forwarded");
+ forwarded["xmlns"] = FORWARD_NS;
+
+ XmlNode delay("delay");
+ delay["xmlns"] = DELAY_NS;
+ delay["stamp"] = utils::to_string(log_line.date.value().timeStamp());
+
+ forwarded.add_child(std::move(delay));
+
+ XmlNode submessage("message");
+ submessage["xmlns"] = CLIENT_NS;
+ submessage["from"] = from + "/" + log_line.nick.value();
+ submessage["type"] = "groupchat";
+
+ XmlNode body("body");
+ body.set_inner(log_line.body.value());
+ submessage.add_child(std::move(body));
+
+ forwarded.add_child(std::move(submessage));
+ result.add_child(std::move(forwarded));
+ message.add_child(std::move(result));
+
+ this->send_stanza(message);
+}
+
+#endif
+
Bridge* BiboumiComponent::get_user_bridge(const std::string& user_jid)
{
auto bare_jid = Jid{user_jid}.bare();
diff --git a/src/xmpp/biboumi_component.hpp b/src/xmpp/biboumi_component.hpp
index 0dbf8f1..1844451 100644
--- a/src/xmpp/biboumi_component.hpp
+++ b/src/xmpp/biboumi_component.hpp
@@ -9,6 +9,10 @@
#include <string>
#include <map>
+namespace db
+{
+class MucLogLine;
+}
struct ListElement;
/**
@@ -82,6 +86,12 @@ public:
void handle_message(const Stanza& stanza);
void handle_iq(const Stanza& stanza);
+#ifdef USE_DATABASE
+ bool handle_mam_request(const Stanza& stanza);
+ void send_archived_message(const db::MucLogLine& log_line, const std::string& from, const std::string& to,
+ const std::string& queryid);
+#endif
+
private:
/**
* Return the bridge associated with the bare JID. Create a new one