summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst2
-rw-r--r--doc/biboumi.1.rst6
-rw-r--r--src/bridge/bridge.cpp7
-rw-r--r--src/bridge/bridge.hpp2
-rw-r--r--src/database/database.hpp2
-rw-r--r--src/xmpp/biboumi_adhoc_commands.cpp16
-rw-r--r--tests/end_to_end/__main__.py6
7 files changed, 37 insertions, 4 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index ee31f7d..bf25e52 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -11,6 +11,8 @@ Version 8.0
- We now properly deal with a PostgreSQL server restart: whenever the
connection is lost with the server, we try to reconnect and re-execute the
query once.
+- A Nick field has been added in the IRC server configuration form, to let
+ the user force a nickname whenever a channel on the server is joined.
Version 7.2 - 2018-01-24
========================
diff --git a/doc/biboumi.1.rst b/doc/biboumi.1.rst
index 2f17823..ccf3985 100644
--- a/doc/biboumi.1.rst
+++ b/doc/biboumi.1.rst
@@ -668,6 +668,12 @@ On a server JID (e.g on the JID chat.freenode.org@biboumi.example.com)
* SHA-1 fingerprint of the TLS certificate to trust: if you know the hash
of the certificate that the server is supposed to use, and you only want
to accept this one, set its SHA-1 hash in this field.
+ * Nickname: A nickname that will be used instead of the nickname provided
+ in the initial presence sent to join a channel. This can be used if the
+ user always wants to have the same nickname on a given server, and not
+ have to bother with setting that nick in all the bookmarks on that
+ server. The nickname can still manually be changed with a standard nick
+ change presence.
* Server password: A password that will be sent just after the connection,
in a PASS command. This is usually used in private servers, where you’re
only allowed to connect if you have the password. Note that, although
diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp
index aba2f05..bff86b9 100644
--- a/src/bridge/bridge.cpp
+++ b/src/bridge/bridge.cpp
@@ -166,10 +166,15 @@ IrcClient* Bridge::find_irc_client(const std::string& hostname) const
}
}
-bool Bridge::join_irc_channel(const Iid& iid, const std::string& nickname, const std::string& password,
+bool Bridge::join_irc_channel(const Iid& iid, std::string nickname, const std::string& password,
const std::string& resource, HistoryLimit history_limit)
{
const auto& hostname = iid.get_server();
+#ifdef USE_DATABASE
+ auto soptions = Database::get_irc_server_options(this->get_bare_jid(), hostname);
+ if (!soptions.col<Database::Nick>().empty())
+ nickname = soptions.col<Database::Nick>();
+#endif
IrcClient* irc = this->make_irc_client(hostname, nickname);
irc->history_limit = history_limit;
this->add_resource_to_server(hostname, resource);
diff --git a/src/bridge/bridge.hpp b/src/bridge/bridge.hpp
index 3798465..a4ee693 100644
--- a/src/bridge/bridge.hpp
+++ b/src/bridge/bridge.hpp
@@ -75,7 +75,7 @@ public:
* Try to join an irc_channel, does nothing and return true if the channel
* was already joined.
*/
- bool join_irc_channel(const Iid& iid, const std::string& nickname, const std::string& password, const std::string& resource, HistoryLimit history_limit);
+ bool join_irc_channel(const Iid& iid, std::string nickname, const std::string& password, const std::string& resource, HistoryLimit history_limit);
void send_channel_message(const Iid& iid, const std::string& body, std::string id);
void send_private_message(const Iid& iid, const std::string& body, const std::string& type="PRIVMSG");
diff --git a/src/database/database.hpp b/src/database/database.hpp
index 5dde447..d986ecc 100644
--- a/src/database/database.hpp
+++ b/src/database/database.hpp
@@ -92,7 +92,7 @@ class Database
using GlobalOptionsTable = Table<Id, Owner, MaxHistoryLength, RecordHistory, GlobalPersistent>;
using GlobalOptions = GlobalOptionsTable::RowType;
- using IrcServerOptionsTable = Table<Id, Owner, Server, Pass, TlsPorts, Ports, Username, Realname, VerifyCert, TrustedFingerprint, EncodingOut, EncodingIn, MaxHistoryLength, Address>;
+ using IrcServerOptionsTable = Table<Id, Owner, Server, Pass, TlsPorts, Ports, Username, Realname, VerifyCert, TrustedFingerprint, EncodingOut, EncodingIn, MaxHistoryLength, Address, Nick>;
using IrcServerOptions = IrcServerOptionsTable::RowType;
using IrcChannelOptionsTable = Table<Id, Owner, Server, Channel, EncodingOut, EncodingIn, MaxHistoryLength, Persistent, RecordHistoryOptional>;
diff --git a/src/xmpp/biboumi_adhoc_commands.cpp b/src/xmpp/biboumi_adhoc_commands.cpp
index d773ec3..66298d4 100644
--- a/src/xmpp/biboumi_adhoc_commands.cpp
+++ b/src/xmpp/biboumi_adhoc_commands.cpp
@@ -293,6 +293,20 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com
}
}
#endif
+
+ {
+ XmlSubNode field(x, "field");
+ field["var"] = "nick";
+ field["type"] = "text-single";
+ field["label"] = "Nickname";
+ field["desc"] = "If set, will override the nickname provided in the initial presence sent to join the first server channel";
+ if (!options.col<Database::Nick>().empty())
+ {
+ XmlSubNode value(field, "value");
+ value.set_inner(options.col<Database::Nick>());
+ }
+ }
+
{
XmlSubNode pass(x, "field");
pass["var"] = "pass";
@@ -427,6 +441,8 @@ void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& com
#endif // BOTAN_FOUND
+ else if (field->get_tag("var") == "nick" && value)
+ options.col<Database::Nick>() = value->get_inner();
else if (field->get_tag("var") == "pass" && value)
options.col<Database::Pass>() = value->get_inner();
diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py
index 914f545..6b97e4a 100644
--- a/tests/end_to_end/__main__.py
+++ b/tests/end_to_end/__main__.py
@@ -2760,6 +2760,7 @@ if __name__ == '__main__':
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='fingerprint']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-private'][@var='pass']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-multi'][@var='after_connect_commands']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='nick']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='username']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='realname']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']",
@@ -2777,6 +2778,7 @@ if __name__ == '__main__':
"<field var='fingerprint'><value>12:12:12</value></field>"
"<field var='pass'><value>coucou</value></field>"
"<field var='after_connect_commands'><value>first command</value><value>second command</value></field>"
+ "<field var='nick'><value>my_nickname</value></field>"
"<field var='username'><value>username</value></field>"
"<field var='realname'><value>realname</value></field>"
"<field var='encoding_out'><value>UTF-8</value></field>"
@@ -2794,6 +2796,7 @@ if __name__ == '__main__':
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='verify_cert']/dataform:value[text()='true']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='fingerprint']/dataform:value[text()='12:12:12']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-private'][@var='pass']/dataform:value[text()='coucou']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='nick']/dataform:value[text()='my_nickname']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-multi'][@var='after_connect_commands']/dataform:value[text()='first command']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-multi'][@var='after_connect_commands']/dataform:value[text()='second command']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='username']/dataform:value[text()='username']",
@@ -2941,6 +2944,7 @@ if __name__ == '__main__':
"<field var='ports' />"
"<field var='tls_ports'><value>7778</value></field>"
"<field var='verify_cert'><value>0</value></field>"
+ "<field var='nick'><value>my_special_nickname</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.']"),
@@ -2950,7 +2954,7 @@ if __name__ == '__main__':
partial(expect_stanza,
"/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"),
partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/my_special_nickname']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
"/presence/muc_user:x/muc_user:status[@code='110']")
),
partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),