|
|
|
@ -13,6 +13,7 @@
|
|
|
|
|
#include <string_view>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <chrono>
|
|
|
|
|
#include <variant>
|
|
|
|
|
#include <fmt/core.h>
|
|
|
|
|
#include <strophe.h>
|
|
|
|
|
|
|
|
|
@ -101,6 +102,86 @@ namespace xml {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
namespace builder {
|
|
|
|
|
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
|
|
|
|
|
|
|
|
|
class spec {
|
|
|
|
|
protected:
|
|
|
|
|
explicit spec(std::string_view tag): tag(tag) {}
|
|
|
|
|
|
|
|
|
|
void child(spec& ch) {
|
|
|
|
|
children.push_back(ch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void attr(std::string k, std::string_view v) {
|
|
|
|
|
attributes[k] = v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void text(std::string_view s) {
|
|
|
|
|
children.push_back(std::string(s));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const std::string tag;
|
|
|
|
|
std::map<std::string, std::string> attributes;
|
|
|
|
|
std::vector<std::variant<spec, std::string>> children;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
std::shared_ptr<xmpp_stanza_t> build(xmpp_ctx_t *context) {
|
|
|
|
|
auto stanza = xmpp_stanza_new(context);
|
|
|
|
|
xmpp_stanza_set_name(stanza, tag.data());
|
|
|
|
|
for (auto& at : attributes) {
|
|
|
|
|
xmpp_stanza_set_attribute(stanza, at.first.data(), at.second.data());
|
|
|
|
|
}
|
|
|
|
|
for (auto& ch : children) {
|
|
|
|
|
std::visit(overloaded {
|
|
|
|
|
[&](spec& child) {
|
|
|
|
|
xmpp_stanza_add_child(stanza, child.build(context).get());
|
|
|
|
|
},
|
|
|
|
|
[&](std::string s) {
|
|
|
|
|
auto child = xmpp_stanza_new(context);
|
|
|
|
|
xmpp_stanza_set_text(child, s.data());
|
|
|
|
|
xmpp_stanza_add_child(stanza, child);
|
|
|
|
|
xmpp_stanza_release(child);
|
|
|
|
|
}
|
|
|
|
|
}, ch);
|
|
|
|
|
}
|
|
|
|
|
return { stanza, &xmpp_stanza_release };
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct body : public spec {
|
|
|
|
|
body() : body("") {}
|
|
|
|
|
body(std::string_view s) : spec("body") {
|
|
|
|
|
text(s);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct message : public spec {
|
|
|
|
|
message() : spec("message") {}
|
|
|
|
|
|
|
|
|
|
message& id(std::string_view s) { attr("id", s); return *this; }
|
|
|
|
|
message& from(std::string_view s) { attr("from", s); return *this; }
|
|
|
|
|
message& to(std::string_view s) { attr("to", s); return *this; }
|
|
|
|
|
message& type(std::string_view s) { attr("type", s); return *this; }
|
|
|
|
|
|
|
|
|
|
message& body(builder::body b) { child(b); return *this; }
|
|
|
|
|
message& body(std::string_view s) { return body(builder::body(s)); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct presence : public spec {
|
|
|
|
|
presence() : spec("presence") {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct iq : public spec {
|
|
|
|
|
iq() : spec("iq") {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct error : public spec {
|
|
|
|
|
error() : spec("error") {}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include "xep-0027.inl"
|
|
|
|
|