summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlouiz’ <louiz@louiz.org>2018-03-04 22:18:58 +0100
committerlouiz’ <louiz@louiz.org>2018-03-12 00:13:59 +0100
commit158d743bf539399e48c64044639b90e5c1705ac1 (patch)
tree5fd7d2846a95e4d6244b10a907a804670c48536f
parent8503d1f6831fc8522a16e0670578d1157d23e116 (diff)
downloadbiboumi-158d743bf539399e48c64044639b90e5c1705ac1.tar.gz
biboumi-158d743bf539399e48c64044639b90e5c1705ac1.tar.bz2
biboumi-158d743bf539399e48c64044639b90e5c1705ac1.tar.xz
biboumi-158d743bf539399e48c64044639b90e5c1705ac1.zip
Remove the virtual channel feature altogether
-rw-r--r--CHANGELOG.rst2
-rw-r--r--doc/biboumi.1.rst35
-rw-r--r--src/bridge/bridge.cpp39
-rw-r--r--src/irc/irc_channel.cpp6
-rw-r--r--src/irc/irc_channel.hpp30
-rw-r--r--src/irc/irc_client.cpp51
-rw-r--r--src/irc/irc_client.hpp14
-rw-r--r--src/xmpp/biboumi_component.cpp3
-rw-r--r--tests/end_to_end/__main__.py114
9 files changed, 24 insertions, 270 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index bcddc11..c6052a1 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,8 @@ Version 8.0
===========
- Add a complete='true' in MAM’s iq result when appropriate
+- The “virtual” channel with an empty name (for example
+ %irc.freenode.net@biboumi) has been entirely removed.
Version 7.2 - 2018-01-24
========================
diff --git a/doc/biboumi.1.rst b/doc/biboumi.1.rst
index 89f8627..2d83dfe 100644
--- a/doc/biboumi.1.rst
+++ b/doc/biboumi.1.rst
@@ -103,16 +103,15 @@ fixed_irc_server
If this option contains the hostname of an IRC server (for example
irc.example.org), then biboumi will enforce the connexion to that IRC
-server only. This means that a JID like ``#chan@biboumi.example.com`` must
-be used instead of ``#chan%irc.example.org@biboumi.example.com``. In that
-mode, the virtual channel (see `Connect to an IRC server`_) is not
-available. The `%` character loses any meaning in the JIDs. It can appear
-in the JID but will not be interpreted as a separator (thus the JID
+server only. This means that a JID like ``#chan@biboumi.example.com``
+must be used instead of ``#chan%irc.example.org@biboumi.example.com``. The
+`%` character loses any meaning in the JIDs. It can appear in the JID but
+will not be interpreted as a separator (thus the JID
``#channel%hello@biboumi.example.com`` points to the channel named
-``#channel%hello`` on the configured IRC server) This option can for example
-be used by an administrator that just wants to let their users join their own
-IRC server using an XMPP client, while forbidding access to any other IRC
-server.
+``#channel%hello`` on the configured IRC server) This option can for
+example be used by an administrator that just wants to let their users
+join their own IRC server using an XMPP client, while forbidding access to
+any other IRC server.
persistent_by_default
---------------------
@@ -295,10 +294,6 @@ the two is based on the first character: by default, if the name starts with
``'#'`` or ``'&'`` (but this can be overridden by the server, using the
ISUPPORT extension) then it’s a channel name, otherwise this is a nickname.
-As a special case, the channel name can also be empty (for example
-``%irc.example.com``), in that case this represents the virtual channel
-provided by biboumi. See `Connect to an IRC server`_ for more details.
-
There is two ways to address an IRC user, using a local part like this:
``nickname`` % ``irc_server`` or by using the in-room address of the
participant, like this:
@@ -336,9 +331,6 @@ Examples:
* ``irc.example.com@biboumi.example.com`` is the IRC server irc.example.com.
-* ``%irc.example.com@biboumi.example.com`` is the virtual channel provided by
- biboumi, for the IRC server irc.example.com.
-
Note: Some JIDs are valid but make no sense in the context of
biboumi:
@@ -362,16 +354,7 @@ Connect to an IRC server
The connection to the IRC server is automatically made when the user tries
to join any channel on that IRC server. The connection is closed whenever
-the last channel on that server is left by the user. To be able to stay
-connected to an IRC server without having to be in a real IRC channel,
-biboumi provides a virtual channel on the jid
-``%irc.example.com@biboumi.example.com``. For example if you want to join the
-channel ``#foo`` on the server ``irc.example.com``, but you need to authenticate
-to a bot of the server before you’re allowed to join it, you can first join
-the room ``%irc.example.com@biboumi.example.com`` (this will effectively
-connect you to the IRC server without joining any channel), then send your
-authentication message to the user ``bot%irc.example.com@biboumi.example.com``
-and finally join the room ``#foo%irc.example.com@biboumi.example.com``.
+the last channel on that server is left by the user.
Roster
------
diff --git a/src/bridge/bridge.cpp b/src/bridge/bridge.cpp
index fefab40..cd3492f 100644
--- a/src/bridge/bridge.cpp
+++ b/src/bridge/bridge.cpp
@@ -63,7 +63,6 @@ void Bridge::shutdown(const std::string& exit_message)
for (auto& pair: this->irc_clients)
{
pair.second->send_quit_command(exit_message);
- pair.second->leave_dummy_channel(exit_message, {});
}
}
@@ -176,35 +175,6 @@ bool Bridge::join_irc_channel(const Iid& iid, const std::string& nickname, const
auto res_in_chan = this->is_resource_in_chan(ChannelKey{iid.get_local(), hostname}, resource);
if (!res_in_chan)
this->add_resource_to_chan(ChannelKey{iid.get_local(), hostname}, resource);
- if (iid.get_local().empty())
- { // Join the dummy channel
- if (irc->is_welcomed())
- {
- if (res_in_chan)
- return false;
- // Immediately simulate a message coming from the IRC server saying that we
- // joined the channel
- if (irc->get_dummy_channel().joined)
- {
- this->generate_channel_join_for_resource(iid, resource);
- }
- else
- {
- const IrcMessage join_message(irc->get_nick(), "JOIN", {""});
- irc->on_channel_join(join_message);
- const IrcMessage end_join_message(std::string(iid.get_server()), "366",
- {irc->get_nick(),
- "", "End of NAMES list"});
- irc->on_channel_completely_joined(end_join_message);
- }
- }
- else
- {
- irc->get_dummy_channel().joining = true;
- irc->start();
- }
- return true;
- }
if (irc->is_channel_joined(iid.get_local()) == false)
{
irc->send_join_command(iid.get_local(), password);
@@ -445,11 +415,7 @@ void Bridge::leave_irc_channel(Iid&& iid, const std::string& status_message, con
#endif
if (channel->joined && !channel->parting && !persistent)
{
- const auto& chan_name = iid.get_local();
- if (chan_name.empty())
- irc->leave_dummy_channel(status_message, resource);
- else
- irc->send_part_command(iid.get_local(), status_message);
+ irc->send_part_command(iid.get_local(), status_message);
}
else if (channel->joined)
{
@@ -1254,9 +1220,6 @@ std::size_t Bridge::number_of_channels_the_resource_is_in(const std::string& irc
res++;
}
- IrcClient* irc = this->find_irc_client(irc_hostname);
- if (irc && (irc->get_dummy_channel().joined || irc->get_dummy_channel().joining))
- res++;
return res;
}
diff --git a/src/irc/irc_channel.cpp b/src/irc/irc_channel.cpp
index 53043c7..1fd34aa 100644
--- a/src/irc/irc_channel.cpp
+++ b/src/irc/irc_channel.cpp
@@ -58,9 +58,3 @@ void IrcChannel::remove_all_users()
this->users.clear();
this->self = nullptr;
}
-
-DummyIrcChannel::DummyIrcChannel():
- IrcChannel(),
- joining(false)
-{
-}
diff --git a/src/irc/irc_channel.hpp b/src/irc/irc_channel.hpp
index 8f85edb..dff1b78 100644
--- a/src/irc/irc_channel.hpp
+++ b/src/irc/irc_channel.hpp
@@ -42,33 +42,3 @@ protected:
IrcUser* self{nullptr};
std::vector<std::unique_ptr<IrcUser>> users{};
};
-
-/**
- * A special channel that is not actually linked to any real irc
- * channel. This is just a channel representing a connection to the
- * server. If an user wants to maintain the connection to the server without
- * having to be on any irc channel of that server, he can just join this
- * dummy channel.
- * It’s not actually dummy because it’s useful and it does things, but well.
- */
-class DummyIrcChannel: public IrcChannel
-{
-public:
- explicit DummyIrcChannel();
- DummyIrcChannel(const DummyIrcChannel&) = delete;
- DummyIrcChannel(DummyIrcChannel&&) = delete;
- DummyIrcChannel& operator=(const DummyIrcChannel&) = delete;
- DummyIrcChannel& operator=(DummyIrcChannel&&) = delete;
-
- /**
- * This flag is at true whenever the user wants to join this channel, but
- * he is not yet connected to the server. When the connection is made, we
- * check that flag and if it’s true, we inform the user that he has just
- * joined that channel.
- * If the user is already connected to the server when he tries to join
- * the channel, we don’t use that flag, we just join it immediately.
- */
- bool joining;
-};
-
-
diff --git a/src/irc/irc_client.cpp b/src/irc/irc_client.cpp
index 40078d9..a866726 100644
--- a/src/irc/irc_client.cpp
+++ b/src/irc/irc_client.cpp
@@ -145,14 +145,6 @@ IrcClient::IrcClient(std::shared_ptr<Poller>& poller, std::string hostname,
chanmodes({"", "", "", ""}),
chantypes({'#', '&'})
{
- this->dummy_channel.topic = "This is a virtual channel provided for "
- "convenience by biboumi, it is not connected "
- "to any actual IRC channel of the server '" + this->hostname +
- "', and sending messages in it has no effect. "
- "Its main goal is to keep the connection to the IRC server "
- "alive without having to join a real channel of that server. "
- "To disconnect from the IRC server, leave this room and all "
- "other IRC channels of that server.";
#ifdef USE_DATABASE
auto options = Database::get_irc_server_options(this->bridge.get_bare_jid(),
this->get_hostname());
@@ -315,8 +307,6 @@ void IrcClient::on_connection_close(const std::string& error_msg)
IrcChannel* IrcClient::get_channel(const std::string& n)
{
- if (n.empty())
- return &this->dummy_channel;
const std::string name = utils::tolower(n);
try
{
@@ -670,10 +660,7 @@ void IrcClient::on_channel_join(const IrcMessage& message)
{
const std::string chan_name = utils::tolower(message.arguments[0]);
IrcChannel* channel;
- if (chan_name.empty())
- channel = &this->dummy_channel;
- else
- channel = this->get_channel(chan_name);
+ channel = this->get_channel(chan_name);
const std::string nick = message.prefix;
IrcUser* user = channel->add_user(nick, this->prefix_to_mode);
if (channel->joined == false)
@@ -948,18 +935,6 @@ void IrcClient::on_welcome_message(const IrcMessage& message)
if (!channels_with_key.empty())
this->send_join_command(channels_with_key, keys);
this->channels_to_join.clear();
- // Indicate that the dummy channel is joined as well, if needed
- if (this->dummy_channel.joining)
- {
- // Simulate a message coming from the IRC server saying that we joined
- // the channel
- const IrcMessage join_message(this->get_nick(), "JOIN", {""});
- this->on_channel_join(join_message);
- const IrcMessage end_join_message(std::string(this->hostname), "366",
- {this->get_nick(),
- "", "End of NAMES list"});
- this->on_channel_completely_joined(end_join_message);
- }
}
void IrcClient::on_part(const IrcMessage& message)
@@ -1062,10 +1037,6 @@ void IrcClient::on_nick(const IrcMessage& message)
}
};
- if (this->get_dummy_channel().joined)
- {
- change_nick_func("", &this->get_dummy_channel());
- }
for (const auto& pair: this->channels)
{
change_nick_func(pair.first, pair.second.get());
@@ -1248,25 +1219,7 @@ void IrcClient::on_unknown_message(const IrcMessage& message)
size_t IrcClient::number_of_joined_channels() const
{
- if (this->dummy_channel.joined)
- return this->channels.size() + 1;
- else
- return this->channels.size();
-}
-
-DummyIrcChannel& IrcClient::get_dummy_channel()
-{
- return this->dummy_channel;
-}
-
-void IrcClient::leave_dummy_channel(const std::string& exit_message, const std::string& resource)
-{
- if (!this->dummy_channel.joined)
- return;
- this->dummy_channel.joined = false;
- this->dummy_channel.joining = false;
- this->dummy_channel.remove_all_users();
- this->bridge.send_muc_leave(Iid("%" + this->hostname, this->chantypes), std::string(this->current_nick), exit_message, true, true, resource);
+ return this->channels.size();
}
#ifdef BOTAN_FOUND
diff --git a/src/irc/irc_client.hpp b/src/irc/irc_client.hpp
index de5c520..fd97fe6 100644
--- a/src/irc/irc_client.hpp
+++ b/src/irc/irc_client.hpp
@@ -279,15 +279,6 @@ public:
* Return the number of joined channels
*/
size_t number_of_joined_channels() const;
- /**
- * Get a reference to the unique dummy channel
- */
- DummyIrcChannel& get_dummy_channel();
- /**
- * Leave the dummy channel: forward a message to the user to indicate that
- * he left it, and mark it as not joined.
- */
- void leave_dummy_channel(const std::string& exit_message, const std::string& resource);
const std::string& get_hostname() const { return this->hostname; }
std::string get_nick() const { return this->current_nick; }
@@ -340,11 +331,6 @@ private:
*/
std::unordered_map<std::string, std::unique_ptr<IrcChannel>> channels;
/**
- * A single channel with a iid of the form "hostname" (normal channel have
- * an iid of the form "chan%hostname".
- */
- DummyIrcChannel dummy_channel;
- /**
* A list of chan we want to join (tuples with the channel name and the
* password, if any), but we need a response 001 from the server before
* sending the actual JOIN commands. So we just keep the channel names in
diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp
index fe6cc1b..891b715 100644
--- a/src/xmpp/biboumi_component.cpp
+++ b/src/xmpp/biboumi_component.cpp
@@ -148,8 +148,7 @@ void BiboumiComponent::handle_presence(const Stanza& stanza)
try {
if (iid.type == Iid::Type::Channel && !iid.get_server().empty())
- { // presence toward a MUC that corresponds to an irc channel, or a
- // dummy channel if iid.chan is empty
+ { // presence toward a MUC that corresponds to an irc channel
if (type.empty())
{
const std::string own_nick = bridge->get_own_nick(iid);
diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py
index 9569321..f09b765 100644
--- a/tests/end_to_end/__main__.py
+++ b/tests/end_to_end/__main__.py
@@ -663,23 +663,6 @@ if __name__ == '__main__':
),
partial(expect_stanza, "/message[@from='#baz%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
]),
- Scenario("virtual_channel",
- [
- handshake_sequence(),
- partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
- connection_begin_sequence("irc.localhost", '{jid_one}/{resource_one}'),
- connection_middle_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_one}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
- "/presence/muc_user:x/muc_user:status[@code='110']")
- ),
- partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
- connection_end_sequence("irc.localhost", '{jid_one}/{resource_one}'),
- partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
- partial(expect_stanza, "/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_one}']"),
- ]),
Scenario("not_connected_error",
[
handshake_sequence(),
@@ -696,34 +679,6 @@ if __name__ == '__main__':
),
partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
]),
- Scenario("irc_server_disconnection",
- [
- handshake_sequence(),
- partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
- connection_begin_sequence("irc.localhost", '{jid_one}/{resource_one}'),
- connection_middle_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_one}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
- "/presence/muc_user:x/muc_user:status[@code='110']")
- ),
- partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
- connection_end_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
-
- partial(expect_unordered, [
- ("/presence[@from='%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='{nick_two}']",
- "/presence/muc_user:x/muc_user:status[@code='110']",
- "/presence/muc_user:x/muc_user:status[@code='303']"),
- ("/presence[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
- ]),
-
- partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
- partial(expect_stanza, "/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_two}']"),
- ]),
Scenario("channel_join_with_two_users",
[
handshake_sequence(),
@@ -1296,27 +1251,27 @@ if __name__ == '__main__':
## Do the exact same thing, from a different chan,
# to check if the response comes from the right JID
- # Join the virtual channel
partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
+ "<presence from='{jid_one}/{resource_one}' to='#dummy%{irc_server_one}/{nick_one}' />"),
+ partial(expect_stanza, "/message"),
partial(expect_stanza,
"/presence/muc_user:x/muc_user:status[@code='110']"),
- partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject"),
+ partial(expect_stanza, "/message[@from='#dummy%{irc_server_one}'][@type='groupchat']/subject"),
# Send a private message, to a in-room JID
- partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' type='chat'><body>re in private</body></message>"),
+ partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='#dummy%{irc_server_one}/{nick_two}' type='chat'><body>re in private</body></message>"),
# Message is received with a server-wide JID
partial(expect_stanza, "/message[@from='{lower_nick_one}%{irc_server_one}'][@to='{jid_two}/{resource_one}'][@type='chat']/body[text()='re in private']"),
# Respond to the message, to the server-wide JID
partial(send_stanza, "<message from='{jid_two}/{resource_one}' to='{lower_nick_one}%{irc_server_one}' type='chat'><body>re</body></message>"),
# The response is received from the in-room JID
- partial(expect_stanza, "/message[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}'][@type='chat']/body[text()='re']"),
+ partial(expect_stanza, "/message[@from='#dummy%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}'][@type='chat']/body[text()='re']"),
# Now we leave the room, to check if the subsequent private messages are still received properly
partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' type='unavailable' />"),
+ "<presence from='{jid_one}/{resource_one}' to='#dummy%{irc_server_one}/{nick_one}' type='unavailable' />"),
partial(expect_stanza,
"/presence[@type='unavailable']/muc_user:x/muc_user:status[@code='110']"),
@@ -1966,8 +1921,6 @@ if __name__ == '__main__':
("/iq[@type='result'][@id='id8'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
"/iq/mam:fin[@complete='true']/rsm:set")),
]),
-
-
Scenario("join_history_limits",
[
handshake_sequence(),
@@ -2002,9 +1955,10 @@ if __name__ == '__main__':
partial(expect_stanza, "/message[@type='groupchat']/body[text()='coucou 4']",
after = partial(save_current_timestamp_plus_delta, "second_timestamp", datetime.timedelta(seconds=1))),
- # join the virtual channel, to stay connected to the server even after leaving #foo
+ # join some other channel, to stay connected to the server even after leaving #foo
partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
+ "<presence from='{jid_one}/{resource_one}' to='#DUMMY%{irc_server_one}/{nick_one}' />"),
+ partial(expect_stanza, "/message"),
partial(expect_stanza, "/presence/muc_user:x/muc_user:status[@code='110']"),
partial(expect_stanza, "/message/subject"),
@@ -2688,56 +2642,6 @@ if __name__ == '__main__':
partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'><x xmlns='http://jabber.org/protocol/muc#user'><invite to='bertrand@example.com'/></x></message>"),
partial(expect_stanza, "/message[@to='bertrand@example.com'][@from='#foo%{irc_server_one}']/muc_user:x/muc_user:invite[@from='{jid_one}/{resource_one}']"),
]),
- Scenario("virtual_channel_multisession",
- [
- handshake_sequence(),
- partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
- connection_begin_sequence("irc.localhost", '{jid_one}/{resource_one}'),
- connection_middle_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_one}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
- "/presence/muc_user:x/muc_user:status[@code='110']")
- ),
- partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
- connection_end_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(send_stanza,
- "<presence from='{jid_one}/{resource_two}' to='%{irc_server_one}/{nick_one}' />"),
-
- partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_two}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
- "/presence/muc_user:x/muc_user:status[@code='110']")
- ),
- partial(expect_stanza, "/message[@to='{jid_one}/{resource_two}'][@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
-
-
- partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
-
- partial(expect_unordered, [
- ("/presence[@from='%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_two}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='Bobby']",
- "/presence/muc_user:x/muc_user:status[@code='303']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
- ("/presence[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_two}']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
-
- ("/presence[@from='%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='Bobby']",
- "/presence/muc_user:x/muc_user:status[@code='303']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
- ("/presence[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
- ]),
-
-
- partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
- partial(expect_stanza, ("/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}']/muc_user:x/muc_user:status[@code='110']",
- "/presence/status[text()='Biboumi note: 1 resources are still in this channel.']",)
- ),
-
- partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_two}' to='%{irc_server_one}/{nick_two}' />"),
- partial(expect_stanza, "/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_two}']"),
- ]),
Scenario("global_configure",
[
handshake_sequence(),