summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlouiz’ <louiz@louiz.org>2017-06-16 10:48:54 +0200
committerlouiz’ <louiz@louiz.org>2017-06-16 10:48:54 +0200
commite75d7ad8ea72044fdfd2317e03f91ba5bea06b86 (patch)
treed6e289cd1026bfcd346956f4eaa378c893119700
parent40db183e3753486deaa43e950fff38579c5ced6f (diff)
downloadbiboumi-e75d7ad8ea72044fdfd2317e03f91ba5bea06b86.tar.gz
biboumi-e75d7ad8ea72044fdfd2317e03f91ba5bea06b86.tar.bz2
biboumi-e75d7ad8ea72044fdfd2317e03f91ba5bea06b86.tar.xz
biboumi-e75d7ad8ea72044fdfd2317e03f91ba5bea06b86.zip
Add a Record History option in the Channel configuration form
fix #3269
-rw-r--r--CHANGELOG.rst2
-rw-r--r--doc/biboumi.1.rst7
-rw-r--r--src/utils/optional_bool.hpp10
-rw-r--r--src/xmpp/biboumi_adhoc_commands.cpp53
-rw-r--r--src/xmpp/biboumi_adhoc_commands.hpp2
-rw-r--r--src/xmpp/biboumi_component.cpp2
-rw-r--r--tests/end_to_end/__main__.py3
7 files changed, 72 insertions, 7 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 9bfecd6..c8cddfe 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -3,6 +3,8 @@ Version 6.0
- The LiteSQL dependency was removed. Only libsqlite3 is now necessary
to work with the database.
+ - The RecordHistory option can now also be configured for each IRC channel,
+ individually.
Version 5.0 - 2017-05-24
========================
diff --git a/doc/biboumi.1.rst b/doc/biboumi.1.rst
index 5396015..4a2225e 100644
--- a/doc/biboumi.1.rst
+++ b/doc/biboumi.1.rst
@@ -358,7 +358,7 @@ History
-------
Public channel messages are saved into archives, inside the database, unless
-the `record_history` option is set to false for that user `Ad-hoc commands`.
+the `record_history` option is set to false by that user (see `Ad-hoc commands`).
Private messages (messages that are sent directly to a nickname, not a
channel) are never stored in the database. When a channel is joined, biboumi
sends the `max_history_length` messages found in the database as the MUC
@@ -631,6 +631,11 @@ On a channel JID (e.g on the JID #test%chat.freenode.org@biboumi.example.com)
the archiving of messages is enabled for this room, the client will
receive the messages that where sent in this channel. This option can be
used to make biboumi act as an IRC bouncer.
+ * Record History: whether or not history messages should be saved in
+ the database, for this specific channel. If the value is “unset” (the
+ default), then the value configured globally is used. This option is there,
+ for example, to be able to enable history recording globally while disabling
+ it for a few specific “private” channels.
Raw IRC messages
----------------
diff --git a/src/utils/optional_bool.hpp b/src/utils/optional_bool.hpp
index 824e76d..59bbbab 100644
--- a/src/utils/optional_bool.hpp
+++ b/src/utils/optional_bool.hpp
@@ -20,6 +20,16 @@ struct OptionalBool
this->is_set = false;
}
+ std::string to_string()
+ {
+ if (this->is_set == false)
+ return "unset";
+ else if (this->value)
+ return "true";
+ else
+ return "false";
+ }
+
bool is_set{false};
bool value{false};
};
diff --git a/src/xmpp/biboumi_adhoc_commands.cpp b/src/xmpp/biboumi_adhoc_commands.cpp
index a13dbb8..ad4faf8 100644
--- a/src/xmpp/biboumi_adhoc_commands.cpp
+++ b/src/xmpp/biboumi_adhoc_commands.cpp
@@ -434,6 +434,26 @@ void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester,
XmlSubNode instructions(x, "instructions");
instructions.set_inner("Edit the form, to configure the settings of the IRC channel "s + iid.get_local());
+ XmlSubNode record_history(x, "field");
+ record_history["var"] = "record_history";
+ record_history["type"] = "list-single";
+ record_history["label"] = "Record history for this channel";
+ record_history["desc"] = "If unset, the value is the one configured globally";
+
+ {
+ // Value selected by default
+ XmlSubNode value(record_history, "value");
+ value.set_inner(options.col<Database::RecordHistoryOptional>().to_string());
+ }
+ // All three possible values
+ for (const auto& val: {"unset", "true", "false"})
+ {
+ XmlSubNode option(record_history, "option");
+ option["label"] = val;
+ XmlSubNode value(option, "value");
+ value.set_inner(val);
+ }
+
XmlSubNode encoding_out(x, "field");
encoding_out["var"] = "encoding_out";
encoding_out["type"] = "text-single";
@@ -471,12 +491,12 @@ void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester,
}
}
-void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node)
+void ConfigureIrcChannelStep2(XmppComponent& xmpp_component, AdhocSession& session, XmlNode& command_node)
{
const Jid owner(session.get_owner_jid());
const Jid target(session.get_target_jid());
- if (handle_irc_channel_configuration_form(command_node, owner, target))
+ if (handle_irc_channel_configuration_form(xmpp_component, command_node, owner, target))
{
command_node.delete_all_children();
XmlSubNode note(command_node, "note");
@@ -492,7 +512,7 @@ void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& co
}
}
-bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& requester, const Jid& target)
+bool handle_irc_channel_configuration_form(XmppComponent& xmpp_component, const XmlNode& node, const Jid& requester, const Jid& target)
{
const XmlNode* x = node.get_child("x", "jabber:x:data");
if (x)
@@ -500,7 +520,7 @@ bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& reque
if (x->get_tag("type") == "submit")
{
const Iid iid(target.local, {});
- auto options = Database::get_irc_channel_options(requester.local + "@" + requester.domain,
+ auto options = Database::get_irc_channel_options(requester.bare(),
iid.get_server(), iid.get_local());
for (const XmlNode *field: x->get_children("field", "jabber:x:data"))
{
@@ -517,6 +537,31 @@ bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& reque
else if (field->get_tag("var") == "persistent" &&
value)
options.col<Database::Persistent>() = to_bool(value->get_inner());
+ else if (field->get_tag("var") == "record_history" &&
+ value && !value->get_inner().empty())
+ {
+ OptionalBool& database_value = options.col<Database::RecordHistoryOptional>();
+ if (value->get_inner() == "true")
+ database_value.set_value(true);
+ else if (value->get_inner() == "false")
+ database_value.set_value(false);
+ else
+ database_value.unset();
+ auto& biboumi_component = dynamic_cast<BiboumiComponent&>(xmpp_component);
+ Bridge* bridge = biboumi_component.find_user_bridge(requester.bare());
+ if (bridge)
+ {
+ if (database_value.is_set)
+ bridge->set_record_history(database_value.value);
+ else
+ { // It is unset, we need to fetch the Global option, to
+ // know if it’s enabled or not
+ auto g_options = Database::get_global_options(requester.bare());
+ bridge->set_record_history(g_options.col<Database::RecordHistory>());
+ }
+ }
+ }
+
}
options.save(Database::db);
diff --git a/src/xmpp/biboumi_adhoc_commands.hpp b/src/xmpp/biboumi_adhoc_commands.hpp
index 7d29cc2..cb6acb9 100644
--- a/src/xmpp/biboumi_adhoc_commands.hpp
+++ b/src/xmpp/biboumi_adhoc_commands.hpp
@@ -20,7 +20,7 @@ void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& com
void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
void insert_irc_channel_configuration_form(XmlNode& node, const Jid& requester, const Jid& target);
void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
-bool handle_irc_channel_configuration_form(const XmlNode& node, const Jid& requester, const Jid& target);
+bool handle_irc_channel_configuration_form(XmppComponent&, const XmlNode& node, const Jid& requester, const Jid& target);
void DisconnectUserFromServerStep1(XmppComponent&, AdhocSession& session, XmlNode& command_node);
void DisconnectUserFromServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node);
diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp
index 881e757..32f3968 100644
--- a/src/xmpp/biboumi_component.cpp
+++ b/src/xmpp/biboumi_component.cpp
@@ -719,7 +719,7 @@ bool BiboumiComponent::handle_room_configuration_form(const XmlNode& query, cons
return false;
Jid requester(from);
- if (!handle_irc_channel_configuration_form(query, requester, to))
+ if (!handle_irc_channel_configuration_form(*this, query, requester, to))
return false;
Stanza iq("iq");
diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py
index 8f108ee..f7fa2ff 100644
--- a/tests/end_to_end/__main__.py
+++ b/tests/end_to_end/__main__.py
@@ -2467,6 +2467,7 @@ if __name__ == '__main__':
partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='list-single'][@var='record_history']/dataform:value[text()='unset']",
),
after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))
),
@@ -2476,6 +2477,7 @@ if __name__ == '__main__':
"<field var='ports' />"
"<field var='encoding_out'><value>UTF-8</value></field>"
"<field var='encoding_in'><value>latin-1</value></field>"
+ "<field var='record_history'><value>true</value></field>"
"</x></command></iq>"),
partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='completed']/commands:note[@type='info'][text()='Configuration successfully applied.']"),
@@ -2484,6 +2486,7 @@ if __name__ == '__main__':
"/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure the IRC channel #foo on server irc.localhost']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']/dataform:value[text()='latin-1']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']/dataform:value[text()='UTF-8']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='list-single'][@var='record_history']/dataform:value[text()='true']",
"/iq/commands:command/commands:actions/commands:next",
),
after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))