bitlbee_config 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,115 @@
1
+ module BitlbeeConfig
2
+ # A BitlBee user account - has channels for control / chat, and accounts with various IM services
3
+ class User
4
+ include BitlbeeConfig::XmlBuildable
5
+
6
+ attr_accessor :nick, :password, :cleartext_password, :version, :settings, :accounts, :channels
7
+
8
+ class << self
9
+ # Rubocop thinks this method is too long, but I think it's more readable than split up
10
+ # rubocop:disable MethodLength
11
+ #
12
+ # @param [Nokogiri::XML::Element] xml XML element to create user from
13
+ # @return [BitlbeeConfig::User] The newly created user
14
+ def from_xml(xml)
15
+ new_user = {}
16
+
17
+ %w(nick password version).each do |att|
18
+ new_user[att.to_sym] = xml.attributes[att].value
19
+ end
20
+
21
+ xml.xpath("setting").each do |setting|
22
+ new_user[setting.attributes["name"].value] = setting.text
23
+ end
24
+
25
+ new_user[:channels] = xml.xpath("channel").collect do |item|
26
+ BitlbeeConfig::Channel.from_xml(item)
27
+ end
28
+
29
+ new_user[:accounts] = xml.xpath("account").collect do |item|
30
+ BitlbeeConfig::Account.from_xml(item)
31
+ end
32
+
33
+ user = BitlbeeConfig::User.new(new_user)
34
+
35
+ user.accounts.each do |account|
36
+ account.user = user
37
+ end
38
+
39
+ user
40
+ end
41
+ # rubocop:enable MethodLength
42
+
43
+ # XML configuration files are currently saved with the downcased username and an xml extension
44
+ #
45
+ # @param [String] username Username to turn into file name
46
+ # @return [String] The file name of the this user's configuration file
47
+ def username_to_filename(username)
48
+ "#{ username.downcase }.xml"
49
+ end
50
+ end
51
+
52
+ # @param [Hash] options
53
+ # @option options [String] :nick Nickname for the user, as it appears in the IRC channel
54
+ # @option options [String] :password The hashed password of the user, as it appears in the XML document
55
+ # @option options [String] :cleartext_password Cleartext password for the user, will be hashed before saving to XML
56
+ # @option options [String] :version I have no idea what this does
57
+ # @option options [Array<BitlbeeConfig::Channel>] :channels Channels for this user
58
+ # @option options [Array<BitlbeeConfig::Account|BitlbeeConfig::Accounts::Icq>] :accounts IM accounts for this user
59
+ # @option options [String] All other entries will be converted to settings
60
+ def initialize(options = {})
61
+ @nick = options.delete(:nick)
62
+ @password = options.delete(:password)
63
+ @cleartext_password = options.delete(:cleartext_password)
64
+ @version = options.delete(:version) || "1"
65
+ @channels = options.delete(:channels) || []
66
+ @accounts = options.delete(:accounts) || []
67
+
68
+ @settings = options || {}
69
+ end
70
+
71
+ # Add an account. If an account with the same id already exists, it will be replaced
72
+ #
73
+ # @param [BitlbeeConfig::Account|BitlbeeConfig::Accounts::Icq] new_account Account to be added
74
+ def add_or_replace_account(new_account)
75
+ @accounts.reject! { |account| account.id == new_account.id }
76
+
77
+ new_account.user = self
78
+ @accounts << new_account
79
+ end
80
+
81
+ # Remove an account by its id
82
+ #
83
+ # @param [String] id_to_remove The account with this ID will be removed
84
+ def remove_account_by_id(id_to_remove)
85
+ @accounts.reject! { |account| account.id == id_to_remove }
86
+ end
87
+
88
+ # Remove an account
89
+ #
90
+ # @param [BitlbeeConfig::Account|BitlbeeConfig::Accounts::Icq] account_to_remove Account to remove
91
+ def remove_account(account_to_remove)
92
+ remove_account_by_id(account_to_remove.id)
93
+ end
94
+
95
+ # If a cleartext password is given, hash it and set password attribute
96
+ def regenerate_password_if_needed
97
+ @password = @cleartext_password.to_bitlbee_password_hash if @cleartext_password
98
+ end
99
+
100
+ # @param [Nokogiri::XML::Builder] xml_builder All XML will be added to this builder
101
+ def build_xml(xml_builder)
102
+ regenerate_password_if_needed
103
+
104
+ to_xml_with_options(xml_builder, nick: @nick, password: @password, version: @version) do |user_xml|
105
+ @accounts.each do |account|
106
+ account.build_xml(user_xml)
107
+ end
108
+
109
+ @channels.each do |channel|
110
+ channel.build_xml(user_xml)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ module BitlbeeConfig
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,28 @@
1
+ # Shipped with Ruby
2
+ # Specified in Gemfile
3
+ require "nokogiri"
4
+ require "mixlib/shellout"
5
+
6
+ # Internal stuff
7
+ require "bitlbee_config/core_extensions"
8
+ require "bitlbee_config/mixins"
9
+ require "bitlbee_config/version"
10
+ require "bitlbee_config/config"
11
+ require "bitlbee_config/account"
12
+ require "bitlbee_config/accounts"
13
+ require "bitlbee_config/channel"
14
+ require "bitlbee_config/user"
15
+
16
+ # rubocop:disable HandleExceptions
17
+ # Development stuff, can't be loaded in production, but that's fine
18
+ %w(debugger).each do |development_gem|
19
+ begin
20
+ require development_gem
21
+ rescue LoadError
22
+ end
23
+ end
24
+ # rubocop:enable HandleExceptions
25
+
26
+ # @author Nils Landt
27
+ module BitlbeeConfig
28
+ end
@@ -0,0 +1,135 @@
1
+ require "helper"
2
+
3
+ describe BitlbeeConfig::Account do
4
+ it "is uniquely identified by protocol and handle" do
5
+ account1 = BitlbeeConfig::Account.new(protocol: :oscar, handle: "1234")
6
+ account2 = BitlbeeConfig::Account.new(protocol: :skype, handle: "1234")
7
+ account3 = BitlbeeConfig::Account.new(protocol: :oscar, handle: "1234")
8
+ account4 = BitlbeeConfig::Account.new(protocol: :skype, handle: "12345")
9
+
10
+ refute account1.id == account2.id
11
+ assert account1.id == account3.id
12
+ refute account2.id == account4.id
13
+ end
14
+
15
+ describe "password regeneration" do
16
+ before do
17
+ @cleartext_password = "cleartext_password"
18
+ @user_cleartext_password = "user_cleartext_password"
19
+ @user = BitlbeeConfig::User.new(nick: "Nils", cleartext_password: @user_cleartext_password)
20
+ @encrypted_password = "encrypted_password"
21
+
22
+ String.any_instance.stubs(:encrypt_bitlbee_password).returns(@cleartext_password + @user_cleartext_password)
23
+ end
24
+
25
+ it "overwrites password if cleartext password AND user cleartext password are given" do
26
+ account = BitlbeeConfig::Account.new(cleartext_password: @cleartext_password,
27
+ user: @user,
28
+ password: @encrypted_password)
29
+
30
+ assert_buildable_object_attribute_equals(account, :password, @cleartext_password.encrypt_bitlbee_password)
31
+ end
32
+
33
+ it "doesn't touch password if no cleartext password is given" do
34
+ account = BitlbeeConfig::Account.new(user: @user,
35
+ password: @encrypted_password)
36
+
37
+ assert_buildable_object_attribute_equals(account, :password, @encrypted_password)
38
+ end
39
+
40
+ it "doesn't touch password if no user cleartext password is given" do
41
+ account = BitlbeeConfig::Account.new(cleartext_password: @cleartext_password,
42
+ password: @encrypted_password)
43
+
44
+ assert_buildable_object_attribute_equals(account, :password, @encrypted_password)
45
+ end
46
+ end
47
+
48
+ describe "creating from xml" do
49
+ before do
50
+ @account = load_config_from_fixture("nils").user.accounts.first
51
+ end
52
+
53
+ it "reads the handle from attribute" do
54
+ assert_equal "12345678", @account.handle
55
+ end
56
+
57
+ it "reads the tag from attribute" do
58
+ assert_equal "icq", @account.tag
59
+ end
60
+
61
+ it "reads the password from attribute" do
62
+ assert_equal "bbbbbbbbbbbbbbbbbbbbb", @account.password
63
+ end
64
+
65
+ it "reads the server from attribute" do
66
+ assert_equal "127.0.0.1", @account.server
67
+ end
68
+
69
+ it "reads the autoconnect flag from attribute" do
70
+ assert_equal "true", @account.autoconnect
71
+ end
72
+
73
+ describe "account creation class based on xml" do
74
+ it "creates a generic account if nothing special is specified" do
75
+ account = BitlbeeConfig::Account.create_new_account
76
+ assert_kind_of BitlbeeConfig::Account, account
77
+ end
78
+
79
+ it "creates an ICQ account when protocol is 'oscar'" do
80
+ account = BitlbeeConfig::Account.create_new_account(protocol: :oscar)
81
+ assert_kind_of BitlbeeConfig::Accounts::Icq, account
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "building xml" do
87
+ it "assigns handle as an attribute" do
88
+ handle = "testhandle"
89
+
90
+ account = BitlbeeConfig::Account.new(handle: handle)
91
+
92
+ assert_buildable_object_attribute_equals(account, :handle, handle)
93
+ end
94
+
95
+ it "assigns protocol as an attribute" do
96
+ protocol = "testprotocol"
97
+
98
+ account = BitlbeeConfig::Account.new(protocol: protocol)
99
+
100
+ assert_buildable_object_attribute_equals(account, :protocol, protocol)
101
+ end
102
+
103
+ it "assigns autoconnect as an attribute" do
104
+ autoconnect = "testautoconnect"
105
+
106
+ account = BitlbeeConfig::Account.new(autoconnect: autoconnect)
107
+
108
+ assert_buildable_object_attribute_equals(account, :autoconnect, autoconnect)
109
+ end
110
+
111
+ it "assigns server as an attribute" do
112
+ server = "testserver"
113
+
114
+ account = BitlbeeConfig::Account.new(server: server)
115
+
116
+ assert_buildable_object_attribute_equals(account, :server, server)
117
+ end
118
+
119
+ it "assigns tag as an attribute" do
120
+ tag = "testtag"
121
+
122
+ account = BitlbeeConfig::Account.new(tag: tag)
123
+
124
+ assert_buildable_object_attribute_equals(account, :tag, tag)
125
+ end
126
+
127
+ it "assigns settings" do
128
+ settings = { nick_format: "%testformat" }
129
+
130
+ account = BitlbeeConfig::Account.new(settings)
131
+
132
+ assert_buildable_object_has_settings(account, settings)
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,82 @@
1
+ require "helper"
2
+
3
+ describe BitlbeeConfig::Accounts::Facebook do
4
+ describe "default settings" do
5
+ before do
6
+ @account = BitlbeeConfig::Accounts::Facebook.new
7
+ end
8
+
9
+ it "sets a tag" do
10
+ assert @account.tag
11
+ end
12
+
13
+ it "sets a nick format" do
14
+ assert @account.settings[:nick_format]
15
+ end
16
+ end
17
+
18
+ describe "username mangling" do
19
+ it "adds the facebook chat name suffix to the username it's not already there" do
20
+ handle = "nilslandt"
21
+ acc = BitlbeeConfig::Accounts::Facebook.new(handle: handle)
22
+
23
+ assert_equal handle + BitlbeeConfig::Accounts::Facebook::USERNAME_SUFFIX, acc.handle
24
+ end
25
+
26
+ it "does not add the facebook chat name suffix if it's already there" do
27
+ handle = "nilslandt" + BitlbeeConfig::Accounts::Facebook::USERNAME_SUFFIX
28
+ acc = BitlbeeConfig::Accounts::Facebook.new(handle: handle)
29
+
30
+ assert_equal handle, acc.handle
31
+ end
32
+
33
+ it "lowercases the username" do
34
+ handle = "NilsLandt" + BitlbeeConfig::Accounts::Facebook::USERNAME_SUFFIX
35
+ acc = BitlbeeConfig::Accounts::Facebook.new(handle: handle)
36
+
37
+ assert_equal handle.downcase, acc.handle
38
+ end
39
+ end
40
+
41
+ describe "authentication strategies" do
42
+ before do
43
+ @oauth_settings = { oauth: "on" }
44
+ end
45
+
46
+ it "uses oauth as default" do
47
+ acc = BitlbeeConfig::Accounts::Facebook.new(handle: "nils")
48
+
49
+ assert_equal :oauth, acc.auth_strategy
50
+ end
51
+
52
+ it "has a password when oauth is used" do
53
+ user = BitlbeeConfig::User.new(nick: "Nils", cleartext_password: "testpwd")
54
+ acc = BitlbeeConfig::Accounts::Facebook.new(handle: "nils", user: user)
55
+ String.any_instance.stubs(:encrypt_bitlbee_password).returns("dontcare")
56
+
57
+ acc.regenerate_password_if_needed
58
+
59
+ assert acc.password.length > 0
60
+ end
61
+
62
+ it "has an oauth setting when oauth strategy is used" do
63
+ acc = BitlbeeConfig::Accounts::Facebook.new(handle: "nils")
64
+
65
+ assert_buildable_object_has_settings acc, @oauth_settings
66
+ end
67
+
68
+ it "has no oauth setting when password strategy is used" do
69
+ acc = BitlbeeConfig::Accounts::Facebook.new(handle: "nils",
70
+ auth_strategy: :password)
71
+
72
+ refute_buildable_object_has_settings acc, @oauth_settings
73
+ end
74
+
75
+ it "should not create an 'auth_strategy' setting" do
76
+ auth_strategy_settings = { auth_strategy: :password }
77
+ acc = BitlbeeConfig::Accounts::Facebook.new(auth_strategy_settings.merge(handle: "nils"))
78
+
79
+ refute_buildable_object_has_settings acc, auth_strategy_settings
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,25 @@
1
+ require "helper"
2
+
3
+ describe BitlbeeConfig::Accounts::Gtalk do
4
+ describe "default settings" do
5
+ before do
6
+ @account = BitlbeeConfig::Accounts::Gtalk.new
7
+ end
8
+
9
+ it "sets a tag" do
10
+ assert @account.tag
11
+ end
12
+
13
+ it "sets a nick format" do
14
+ assert @account.settings[:nick_format]
15
+ end
16
+
17
+ it "sets a server" do
18
+ assert @account.server
19
+ end
20
+
21
+ it "enables oauth" do
22
+ assert @account.settings[:oauth]
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ require "helper"
2
+
3
+ describe BitlbeeConfig::Accounts::Hipchat do
4
+ describe "default settings" do
5
+ before do
6
+ @account = BitlbeeConfig::Accounts::Hipchat.new
7
+ end
8
+
9
+ it "sets a tag" do
10
+ assert @account.tag
11
+ end
12
+
13
+ it "sets a nick format" do
14
+ assert @account.settings[:nick_format]
15
+ end
16
+ end
17
+
18
+ describe "username mangling" do
19
+ it "adds the hipchat chat name suffix to the username it's not already there" do
20
+ handle = "nilslandt"
21
+ acc = BitlbeeConfig::Accounts::Hipchat.new(handle: handle)
22
+
23
+ assert_equal handle + BitlbeeConfig::Accounts::Hipchat::USERNAME_SUFFIX, acc.handle
24
+ end
25
+
26
+ it "does not add the hipchat chat name suffix if it's already there" do
27
+ handle = "nilslandt" + BitlbeeConfig::Accounts::Hipchat::USERNAME_SUFFIX
28
+ acc = BitlbeeConfig::Accounts::Hipchat.new(handle: handle)
29
+
30
+ assert_equal handle, acc.handle
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,55 @@
1
+ require "helper"
2
+
3
+ describe BitlbeeConfig::Channel do
4
+ it "turns all unrecognized options into settings" do
5
+ settings = { testsetting: "testvalue", settingtwo: "valuetwo" }
6
+
7
+ channel = BitlbeeConfig::Channel.new(settings)
8
+
9
+ assert_equal settings, channel.settings
10
+ end
11
+
12
+ describe "creating from xml" do
13
+ before do
14
+ @channel = load_config_from_fixture("nils").user.channels.first
15
+ end
16
+
17
+ it "reads the name from attribute" do
18
+ assert_equal "&bitlbee", @channel.name
19
+ end
20
+
21
+ it "reads the type from attribute" do
22
+ assert_equal "control", @channel.type
23
+ end
24
+
25
+ it "reads settings from sub elements" do
26
+ assert_equal({ auto_join: "true" }, @channel.settings)
27
+ end
28
+ end
29
+
30
+ describe "building xml" do
31
+ it "assigns name as an attribute" do
32
+ name = "testchannel"
33
+
34
+ channel = BitlbeeConfig::Channel.new(name: name)
35
+
36
+ assert_buildable_object_attribute_equals(channel, :name, name)
37
+ end
38
+
39
+ it "assigns type as an attribute" do
40
+ type = "local"
41
+
42
+ channel = BitlbeeConfig::Channel.new(type: type)
43
+
44
+ assert_buildable_object_attribute_equals(channel, :type, type)
45
+ end
46
+
47
+ it "assigns settings as sub elements" do
48
+ settings = { testsetting: "testvalue" }
49
+
50
+ channel = BitlbeeConfig::Channel.new(settings)
51
+
52
+ assert_buildable_object_has_settings(channel, settings)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,118 @@
1
+ require "helper"
2
+
3
+ describe BitlbeeConfig::Config do
4
+ it "initializes with a single given user" do
5
+ new_user = BitlbeeConfig::User.new(nick: "test")
6
+ config = BitlbeeConfig::Config.new(user: new_user)
7
+
8
+ assert_kind_of BitlbeeConfig::User, config.user
9
+ assert_equal config.user, new_user
10
+ end
11
+
12
+ describe "deleting user configuration files" do
13
+ before do
14
+ @config_dir = get_tmp_dir
15
+ FileUtils.cp([get_fixture_by_name("nils"), get_fixture_by_name("malte")], @config_dir)
16
+ end
17
+
18
+ it "deletes a user configuration file from a given directory" do
19
+ assert File.exists?(File.join(@config_dir, "nils.xml"))
20
+
21
+ BitlbeeConfig::Config.delete_from_directory_for_user(@config_dir, "Nils")
22
+
23
+ refute File.exists?(File.join(@config_dir, "nils.xml"))
24
+ assert File.exists?(File.join(@config_dir, "malte.xml"))
25
+ end
26
+
27
+ after do
28
+ FileUtils.rm_rf @config_dir
29
+ end
30
+ end
31
+
32
+ describe "saving to file system" do
33
+ before do
34
+ @output_dir = get_tmp_dir
35
+ end
36
+
37
+ it "creates a file for every user" do
38
+ user_names = %w(user_one user_two)
39
+
40
+ configs = user_names.collect do |user_name|
41
+ BitlbeeConfig::Config.new(user: BitlbeeConfig::User.new(nick: user_name))
42
+ end
43
+
44
+ configs.each { |config| config.save_to_directory(@output_dir) }
45
+
46
+ user_names.each do |user_name|
47
+ assert File.exists?(File.join(@output_dir, "#{ user_name }.xml"))
48
+ end
49
+ end
50
+
51
+ it "downcases all filenames" do
52
+ user_name = "Nils"
53
+
54
+ config = BitlbeeConfig::Config.new(user: BitlbeeConfig::User.new(nick: user_name))
55
+ config.save_to_directory(@output_dir)
56
+
57
+ assert File.exists?(File.join(@output_dir, "#{ user_name.downcase }.xml"))
58
+ end
59
+
60
+ after do
61
+ FileUtils.rm_rf @output_dir
62
+ end
63
+ end
64
+
65
+ describe "conversion to string" do
66
+ it "delegates building each user to the user object" do
67
+ user = BitlbeeConfig::User.new(nick: "Nils")
68
+ user.expects(:build_xml).once
69
+
70
+ config = BitlbeeConfig::Config.new(user: user)
71
+
72
+ # rubocop:disable HandleExceptions
73
+ # since "build_xml" is stubbed, nothing will be built, resulting in an error. That's fine for this test
74
+ begin
75
+ config.to_xml
76
+ rescue NoMethodError
77
+ end
78
+ # rubocop:enable HandleExceptions
79
+ end
80
+ end
81
+
82
+ describe "creating from xml" do
83
+ describe "reading multiple xml files from directory" do
84
+ before do
85
+ @config_dir = get_tmp_dir
86
+ FileUtils.cp([get_fixture_by_name("nils"), get_fixture_by_name("malte")], @config_dir)
87
+ end
88
+
89
+ it "creates multiple configs for multiple files in a directory" do
90
+ configs = BitlbeeConfig::Config.from_directory(@config_dir)
91
+
92
+ assert_equal 2, configs.count
93
+ assert configs.all? { |config| config.is_a?(BitlbeeConfig::Config) }
94
+ end
95
+
96
+ it "loads config for a specific user from a given directory" do
97
+ config = BitlbeeConfig::Config.from_directory_for_user(@config_dir, "nils")
98
+
99
+ assert_kind_of BitlbeeConfig::User, config.user
100
+ assert_equal "Nils", config.user.nick
101
+ end
102
+
103
+ after do
104
+ FileUtils.rm_rf @config_dir
105
+ end
106
+ end
107
+
108
+ it "finds a user in an xml config" do
109
+ config = load_config_from_fixture "nils"
110
+ assert_equal config.user.nick, "Nils"
111
+ end
112
+
113
+ it "delegates the user to a new user object" do
114
+ BitlbeeConfig::User.expects(:from_xml).once
115
+ load_config_from_fixture "nils"
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,43 @@
1
+ require "helper"
2
+
3
+ describe String do
4
+ describe "#to_bitlbee_password_hash" do
5
+ it "shells out to bitlbee" do
6
+ shellout = mocked_shellout
7
+ Mixlib::ShellOut.stubs(:new).returns(shellout)
8
+ shellout.expects(:run_command)
9
+
10
+ "test".to_bitlbee_password_hash
11
+ end
12
+ end
13
+
14
+ describe "#matches_bitlbee_password_hash?" do
15
+ it "shells out to bitlbee" do
16
+ shellout = mocked_shellout
17
+ Mixlib::ShellOut.stubs(:new).returns(shellout)
18
+ shellout.expects(:run_command)
19
+
20
+ "test".matches_bitlbee_password_hash?("123456")
21
+ end
22
+ end
23
+
24
+ describe "#encrypt_bitlbee_password" do
25
+ it "shells out to bitlbee" do
26
+ shellout = mocked_shellout
27
+ Mixlib::ShellOut.stubs(:new).returns(shellout)
28
+ shellout.expects(:run_command)
29
+
30
+ "test".encrypt_bitlbee_password("key")
31
+ end
32
+ end
33
+
34
+ describe "#decrypt_bitlbee_password" do
35
+ it "shells out to bitlbee" do
36
+ shellout = mocked_shellout
37
+ Mixlib::ShellOut.stubs(:new).returns(shellout)
38
+ shellout.expects(:run_command)
39
+
40
+ "test".decrypt_bitlbee_password("key")
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,8 @@
1
+ <user nick="Malte" password="cccccccccccccccccccccccccccc" version="1">
2
+ <setting name="away">I&apos;m busy</setting>
3
+ <setting name="last_version">197120</setting>
4
+ <account protocol="oscar" handle="87654321" password="ddddddddddddddddddddd" autoconnect="true" tag="icq"/>
5
+ <channel name="&amp;bitlbee" type="control">
6
+ <setting name="auto_join">true</setting>
7
+ </channel>
8
+ </user>
@@ -0,0 +1,8 @@
1
+ <user nick="Nils" password="aaaaaaaaaaaaaaaaaaaaaaaaaaaa" version="1">
2
+ <setting name="away">I&apos;m busy</setting>
3
+ <setting name="last_version">197120</setting>
4
+ <account protocol="oscar" handle="12345678" password="bbbbbbbbbbbbbbbbbbbbb" autoconnect="true" tag="icq" server="127.0.0.1"/>
5
+ <channel name="&amp;bitlbee" type="control">
6
+ <setting name="auto_join">true</setting>
7
+ </channel>
8
+ </user>