muc errors

master
bqv 3 years ago
parent 35f6355e08
commit 74b6edbfb5
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910

@ -123,6 +123,16 @@ int connection__presence_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void
channel = channel__new(account, CHANNEL_TYPE_PM, binding.from->bare.data(), binding.from->bare.data()); channel = channel__new(account, CHANNEL_TYPE_PM, binding.from->bare.data(), binding.from->bare.data());
} }
if (binding.type && *binding.type == "error" && binding.muc() && channel)
{
if (auto error = binding.error())
{
weechat_printf(channel->buffer, "%sError joining MUC: %s",
weechat_prefix("network"), error->reason());
}
return 1;
}
if (auto x = binding.muc_user()) if (auto x = binding.muc_user())
{ {
for (int& status : x->statuses) for (int& status : x->statuses)

@ -217,9 +217,132 @@ namespace xml {
std::vector<int> statuses; std::vector<int> statuses;
}; };
class error { // THIS IS RFC 6120 :(
private:
enum condition : int {
not_authorized,
registration_required,
forbidden,
not_allowed,
not_acceptable,
conflict,
service_unavailable,
item_not_found
};
enum class action {
auth,
cancel,
continue_,
modify,
wait
};
static action parse_action(std::string_view s) {
if (s == "auth")
return action::auth;
else if (s == "cancel")
return action::cancel;
else if (s == "continue")
return action::continue_;
else if (s == "modify")
return action::modify;
else if (s == "wait")
return action::wait;
throw std::invalid_argument(
fmt::format("Bad action: {}", s));
}
static std::string_view format_action(action e) {
switch (e) {
case action::auth:
return "auth";
case action::cancel:
return "cancel";
case action::continue_:
return "continue";
case action::modify:
return "modify";
case action::wait:
return "wait";
default:
return "";
}
}
public:
error(node& node) {
if (auto attr = node.get_attr("by"))
by = jid(node.context, *attr);
if (auto attr = node.get_attr("type"))
type = parse_action(*attr);
using xmpp_stanzas = urn::ietf::params::xml::ns::xmpp_stanzas;
for (auto& child : node.get_children<xmpp_stanzas>("not-authorized"))
condition = not_authorized;
for (auto& child : node.get_children<xmpp_stanzas>("forbidden"))
condition = forbidden;
for (auto& child : node.get_children<xmpp_stanzas>("item-not-found"))
condition = item_not_found;
for (auto& child : node.get_children<xmpp_stanzas>("not-allowed"))
condition = not_allowed;
for (auto& child : node.get_children<xmpp_stanzas>("not-acceptable"))
condition = not_acceptable;
for (auto& child : node.get_children<xmpp_stanzas>("registration-required"))
condition = registration_required;
for (auto& child : node.get_children<xmpp_stanzas>("conflict"))
condition = conflict;
for (auto& child : node.get_children<xmpp_stanzas>("service-unavailable"))
condition = service_unavailable;
for (auto& child : node.get_children("text"))
description = child.get().text;
}
std::optional<jid> by;
std::optional<enum action> type;
std::optional<enum condition> condition;
std::optional<std::string> description;
const char* reason() {
switch (condition)
{
case not_authorized:
return "Password Required";
case forbidden:
return "Banned";
case item_not_found:
return "No such MUC";
case not_allowed:
return "MUC Creation Failed";
case not_acceptable:
return "Unacceptable Nickname";
case registration_required:
return "Not on Member List";
case conflict:
return "Nickname Conflict";
case service_unavailable:
return "Service Unavailable (MUC Full?)";
}
return "Unspecified";
}
};
private: private:
std::optional<bool> _muc;
std::optional<std::optional<x>> _muc_user; std::optional<std::optional<x>> _muc_user;
std::optional<std::optional<error>> _error;
public: public:
bool muc() {
if (!_muc)
{
auto child = get_children<jabber_org::protocol::muc>("x");
_muc = child.size() > 0;
}
return *_muc;
}
std::optional<x>& muc_user() { std::optional<x>& muc_user() {
if (!_muc_user) if (!_muc_user)
{ {
@ -231,6 +354,18 @@ namespace xml {
} }
return *_muc_user; return *_muc_user;
} }
std::optional<error>& error() {
if (!_error)
{
auto child = get_children("error");
if (child.size() > 0)
_error = child.front().get();
else
_error.emplace(std::nullopt);
}
return *_error;
}
}; };
} }

@ -44,7 +44,8 @@ namespace xml{
auto child = get_children<jabber_org::protocol::caps>("c"); auto child = get_children<jabber_org::protocol::caps>("c");
if (child.size() > 0) if (child.size() > 0)
_capabilities = caps(child.front().get()); _capabilities = caps(child.front().get());
_capabilities.emplace(std::nullopt); else
_capabilities.emplace(std::nullopt);
} }
return *_capabilities; return *_capabilities;
} }

@ -28,17 +28,17 @@ namespace xml {
if (children.size() <= 0) if (children.size() <= 0)
_idle_since.emplace(std::nullopt); _idle_since.emplace(std::nullopt);
else { else {
auto since = children.front().get().get_attr("since"); auto since = children.front().get().get_attr("since");
if (!since) if (!since)
_idle_since.emplace(std::nullopt); _idle_since.emplace(std::nullopt);
else { else {
try { try {
_idle_since = get_time(*since); _idle_since = get_time(*since);
} }
catch (const std::invalid_argument& ex) { catch (const std::invalid_argument& ex) {
_idle_since.emplace(std::nullopt); _idle_since.emplace(std::nullopt);
} }
} }
} }
} }
return *_idle_since; return *_idle_since;

Loading…
Cancel
Save