diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/database/database.cpp | 10 | ||||
-rw-r--r-- | src/xmpp/biboumi_component.cpp | 79 | ||||
-rw-r--r-- | src/xmpp/biboumi_component.hpp | 10 |
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 |