~singpolyma/biboumi

1fc3fa1bd8d98d45d18e8af76202cbf6b757b369 — Florent Le Coz 6 years ago 421c960
Add an ad-hoc configure command on IRC channels

Include encodingIn and encodingOut options, unused at the moment
M src/xmpp/biboumi_adhoc_commands.cpp => src/xmpp/biboumi_adhoc_commands.cpp +90 -0
@@ 312,6 312,96 @@ void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& com
  command_node.add_child(std::move(error));
  session.terminate();
}

void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node)
{
  const Jid owner(session.get_owner_jid());
  const Jid target(session.get_target_jid());
  const Iid iid(target.local);
  auto options = Database::get_irc_channel_options_with_server_default(owner.local + "@" + owner.domain,
                                                                       iid.get_server(), iid.get_local());

  XmlNode x("jabber:x:data:x");
  x["type"] = "form";
  XmlNode title("title");
  title.set_inner("Configure the IRC channel "s + iid.get_local() + " on server "s + iid.get_server());
  x.add_child(std::move(title));
  XmlNode instructions("instructions");
  instructions.set_inner("Edit the form, to configure the settings of the IRC channel "s + iid.get_local());
  x.add_child(std::move(instructions));

  XmlNode required("required");

  XmlNode encoding_out("field");
  encoding_out["var"] = "encoding_out";
  encoding_out["type"] = "text-single";
  encoding_out["desc"] = "The encoding used when sending messages to the IRC server. Defaults to the server's “out encoding” if unset for the channel";
  encoding_out["label"] = "Out encoding";
  if (!options.encodingOut.value().empty())
    {
      XmlNode encoding_out_value("value");
      encoding_out_value.set_inner(options.encodingOut.value());
      encoding_out.add_child(std::move(encoding_out_value));
    }
  encoding_out.add_child(required);
  x.add_child(std::move(encoding_out));

  XmlNode encoding_in("field");
  encoding_in["var"] = "encoding_in";
  encoding_in["type"] = "text-single";
  encoding_in["desc"] = "The encoding used to decode message received from the IRC server. Defaults to the server's “in encoding” if unset for the channel";
  encoding_in["label"] = "In encoding";
  if (!options.encodingIn.value().empty())
    {
      XmlNode encoding_in_value("value");
      encoding_in_value.set_inner(options.encodingIn.value());
      encoding_in.add_child(std::move(encoding_in_value));
    }
  encoding_in.add_child(required);
  x.add_child(std::move(encoding_in));

  command_node.add_child(std::move(x));
}

void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
{
  const XmlNode* x = command_node.get_child("x", "jabber:x:data");
  if (x)
    {
      const Jid owner(session.get_owner_jid());
      const Jid target(session.get_target_jid());
      const Iid iid(target.local);
      auto options = Database::get_irc_channel_options(owner.local + "@" + owner.domain,
                                                       iid.get_server(), iid.get_local());
      for (const XmlNode* field: x->get_children("field", "jabber:x:data"))
        {
          const XmlNode* value = field->get_child("value", "jabber:x:data");

          if (field->get_tag("var") == "encoding_out" &&
                   value && !value->get_inner().empty())
            options.encodingOut = value->get_inner();

          else if (field->get_tag("var") == "encoding_in" &&
                   value && !value->get_inner().empty())
            options.encodingIn = value->get_inner();
        }

      options.update();

      command_node.delete_all_children();
      XmlNode note("note");
      note["type"] = "info";
      note.set_inner("Configuration successfully applied.");
      command_node.add_child(std::move(note));
      return;
    }
  XmlNode error(ADHOC_NS":error");
  error["type"] = "modify";
  XmlNode condition(STANZA_NS":bad-request");
  error.add_child(std::move(condition));
  command_node.add_child(std::move(error));
  session.terminate();
}
#endif  // USE_DATABASE

void DisconnectUserFromServerStep1(XmppComponent& xmpp_component, AdhocSession& session, XmlNode& command_node)

M src/xmpp/biboumi_adhoc_commands.hpp => src/xmpp/biboumi_adhoc_commands.hpp +3 -0
@@ 13,6 13,9 @@ void DisconnectUserStep2(XmppComponent&, AdhocSession& session, XmlNode& command
void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);

void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);

void DisconnectUserFromServerStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
void DisconnectUserFromServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
void DisconnectUserFromServerStep3(XmppComponent&, AdhocSession& session, XmlNode& command_node);

M src/xmpp/biboumi_component.cpp => src/xmpp/biboumi_component.cpp +15 -1
@@ 43,7 43,8 @@ static std::set<std::string> kickable_errors{

BiboumiComponent::BiboumiComponent(std::shared_ptr<Poller> poller, const std::string& hostname, const std::string& secret):
  XmppComponent(poller, hostname, secret),
  irc_server_adhoc_commands_handler(*this)
  irc_server_adhoc_commands_handler(*this),
  irc_channel_adhoc_commands_handler(*this)
{
  this->stanza_handlers.emplace("presence",
                                std::bind(&BiboumiComponent::handle_presence, this,std::placeholders::_1));


@@ 65,6 66,9 @@ BiboumiComponent::BiboumiComponent(std::shared_ptr<Poller> poller, const std::st
    {"configure", AdhocCommand({&ConfigureIrcServerStep1, &ConfigureIrcServerStep2}, "Configure a few settings for that IRC server", false)},
#endif
  };
  this->irc_channel_adhoc_commands_handler.get_commands() = {
    {"configure", AdhocCommand({&ConfigureIrcChannelStep1, &ConfigureIrcChannelStep2}, "Configure a few settings for that IRC channel", false)},
  };
}

void BiboumiComponent::shutdown()


@@ 331,6 335,8 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
          AdhocCommandsHandler* adhoc_handler;
          if (!to.local.empty() && !iid.is_user && !iid.is_channel)
            adhoc_handler = &this->irc_server_adhoc_commands_handler;
          else if (!to.local.empty() && iid.is_channel)
            adhoc_handler = &this->irc_channel_adhoc_commands_handler;
          else
            adhoc_handler = &this->adhoc_commands_handler;



@@ 407,6 413,14 @@ void BiboumiComponent::handle_iq(const Stanza& stanza)
                                                 this->irc_server_adhoc_commands_handler);
                  stanza_error.disable();
                }
              else if (!iid.is_user && iid.is_channel)
                {               // Get the channel's adhoc commands
                  this->send_adhoc_commands_list(id, from, to_str,
                                                 (Config::get("admin", "") ==
                                                  from_jid.bare()),
                                                 this->irc_channel_adhoc_commands_handler);
                  stanza_error.disable();
                }
            }
          else if (node.empty() && !iid.is_user && !iid.is_channel)
            { // Disco on an IRC server: get the list of channels

M src/xmpp/biboumi_component.hpp => src/xmpp/biboumi_component.hpp +1 -0
@@ 98,6 98,7 @@ private:
  std::unordered_map<std::string, std::unique_ptr<Bridge>> bridges;

  AdhocCommandsHandler irc_server_adhoc_commands_handler;
  AdhocCommandsHandler irc_channel_adhoc_commands_handler;

  BiboumiComponent(const BiboumiComponent&) = delete;
  BiboumiComponent(BiboumiComponent&&) = delete;