teamspeak3 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5cfaad253891919553b8e8f9195e6c903a43e94f
4
- data.tar.gz: 4b4a47e6af3efea58d63e32f004efb660eae2909
3
+ metadata.gz: 1f29c3659a40d129e7a749f5d3e91bc11530718f
4
+ data.tar.gz: f5c472bdbae695325c1882fa9231aaa5da62bac5
5
5
  SHA512:
6
- metadata.gz: 4f2d97920b5994b11b4deb306296e9eef01e1f3d3d55ab62ea92e47e7de5acd3d55566c49e7be9d6becaa4907b391ce46938aaa10a48646121fb7e352c060288
7
- data.tar.gz: a4e43cb8cb9ed5eb8c940e237102d6f9b95c6fdf436d9f31b01923dcfa62727a00c2817dc130553a1ea4db578a90ee35c94f956f4090528ff04a2951e6950837
6
+ metadata.gz: 7d125a3d63f88d2340357f42ff3860e15d18d8c284f7a682ae8213ab2c6a9926b8ddd9013dda593234c7feddabdfbffad32c6c4ebb7f047067c9d3a7ca6cd715
7
+ data.tar.gz: 80f2694136606027b437b7e19e2da9dd2e3c417e177900666f6da0959e5fe798eb0d1dfdf3f1979a73f181002d0e144e8bb9420c93723d2405e51aad5e852bb2
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --format documentation
@@ -0,0 +1,34 @@
1
+ ## Release 0.0.4 (2018-03-11)
2
+
3
+ * Add `TeamSpeak3::VERSION` to fetch the current version of this library.
4
+ * Add `TeamSpeak3::Client#send_message` to allow to send messages directly via the client object
5
+ without going all the way down to the `TeamSpeak3::Server#send_message`
6
+ * Add `TeamSpeak3::VirtualServer#execute` method which is basically a wrapper for `TeamSpeak3::Server#execute`
7
+ but it always sets the active virtual server correctly.
8
+ * EOF errors will now be handled on connection attempts. (an EOF error will be raised when a connection has
9
+ been established but gets closed immediately)
10
+ * Command execution on TeamSpeak 3 servers (TeamSpeak3::Server#execute) has been refactored.
11
+ * Add `TeamSpeak3::Server#prepare_command` to build a command that can be executed safely (internally used by
12
+ `TeamSpeak3::Server#execute`)
13
+ * Add `TeamSpeak3::ChannelCollection` that represents an array of channels for a virtual server (abstraction of `Array`)
14
+ * `TeamSpeak3::VirtualServer#channels` now returns an instance of `TeamSpeak3::ChannelCollection`
15
+ * Channels can now be created through `TeamSpeak3::ChannelCollection#create`
16
+ * Channels can now be found with their ID via `TeamSpeak3::ChannelCollection#find`
17
+
18
+ ## Release 0.0.3 (cancelled/skipped)
19
+
20
+ - This version has been cancelled and skipped -
21
+
22
+ ## Release 0.0.2 (2018-03-05)
23
+
24
+ * `TeamSpeak3::VirtualServer` class was added to handle virtual servers.
25
+ * `TeamSpeak3::Channel` class was added to handle channels on virtual servers.
26
+ * `TeamSpeak3::Client` class was added to act on clients.
27
+ * New `attr_reader`'s were added to `TeamSpeak3::Server` (`ip_address` and `query_port`)
28
+ * Added `send_message_to` to class `TeamSpeak3::Server` to send messages to different targets (available targets: server, client, channel)
29
+ * Added method `kick_client!` to `TeamSpeak3::Server` which is being used by the `TeamSpeak3::Client` class to kick clients from servers or channels.
30
+ * Added `select_server` to `TeamSpeak3::Server` to select the current active virtual servers (this is required by the query interface of TeamSpeak 3). In general it should not be required to use this method at all because it's handled by the methods internally.
31
+
32
+ ## Release 0.0.1 (2018-03-04)
33
+
34
+ * Add basic TeamSpeak 3 server connection handling
@@ -0,0 +1,34 @@
1
+ # TeamSpeak 3 Query Library
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/teamspeak3.svg)](http://badge.fury.io/rb/teamspeak3)
4
+
5
+ **NOTE: This library is currently being developed and should not be used for production purposes!**
6
+
7
+ An OOP library to query and manage TeamSpeak 3 servers in Ruby.
8
+
9
+ ## Installation
10
+
11
+ ```
12
+ gem install teamspeak3
13
+ ```
14
+
15
+ ## Getting Started
16
+
17
+ ```ruby
18
+ require 'teamspeak3'
19
+
20
+ server = TeamSpeak3::Server.new('127.0.0.1', 10011)
21
+ server.login 'serveradmin', 'password'
22
+ ```
23
+
24
+ ## Contribution
25
+
26
+ If you want to suggest new features or report bugs, feel free to open an issue [here](https://github.com/mschnitzer/teamspeak3/issues/new).
27
+
28
+ If you want to contribute to the code base:
29
+
30
+ 1. Fork this repository
31
+ 2. Create a new branch
32
+ 3. Do your changes
33
+ 4. Push them to GitHub
34
+ 5. Open a pull request against the `master` branch
@@ -57,6 +57,27 @@ module TeamSpeak3
57
57
  @max_family_clients = params[:channel_maxfamilyclients].to_i
58
58
  end
59
59
 
60
+ def self.create(virtual_server, name, opts = {})
61
+ command_parameters = { channel_name: name }
62
+
63
+ command_parameters[:channel_topic] = opts[:topic] if opts[:topic]
64
+ command_parameters[:channel_description] = opts[:description] if opts[:description]
65
+ command_parameters[:channel_password] = opts[:password] if opts[:password]
66
+ command_parameters[:channel_codec] = opts[:codec] if opts[:codec]
67
+ command_parameters[:channel_codec_quality] = opts[:codec_quality] if opts[:codec_quality]
68
+ command_parameters[:channel_maxclients] = opts[:max_clients] if opts[:max_clients]
69
+ command_parameters[:channel_maxfamilyclients] = opts[:max_family_clients] if opts[:max_family_clients]
70
+ command_parameters[:channel_order] = opts[:order] if opts[:order]
71
+ command_parameters[:channel_needed_talk_power] = opts[:needed_talk_power] if opts[:needed_talk_power]
72
+ command_parameters[:channel_name_phonetic] = opts[:name_phonetic] if opts[:name_phonetic]
73
+ command_parameters[:channel_icon_id] = opts[:icon_id] if opts[:icon_id]
74
+ command_parameters[:channel_codec_is_unencrypted] = opts[:codec_is_unencrypted] if opts[:codec_is_unencrypted]
75
+ command_parameters[:cpid] = opts[:parent_id] if opts[:parent_id]
76
+
77
+ response = virtual_server.execute :channelcreate, command_parameters
78
+ virtual_server.channels.find(response[:data].first[:cid])
79
+ end
80
+
60
81
  def codec_name
61
82
  return "Speex Narrowband" if @codec == 0
62
83
  return "Speex Wideband" if @codec == 1
@@ -0,0 +1,19 @@
1
+ module TeamSpeak3
2
+ class ChannelCollection < Array
3
+ def initialize(virtual_server)
4
+ @virtual_server = virtual_server
5
+ end
6
+
7
+ def create(name, opts = {})
8
+ Channel.create(@virtual_server, name, opts)
9
+ end
10
+
11
+ def find(id)
12
+ self.each do |channel|
13
+ return channel if channel.id == id.to_i
14
+ end
15
+
16
+ nil
17
+ end
18
+ end
19
+ end
@@ -111,6 +111,10 @@ module TeamSpeak3
111
111
  @recording
112
112
  end
113
113
 
114
+ def send_message(message)
115
+ virtual_server.server.send_message_to(self, message)
116
+ end
117
+
114
118
  def talker?
115
119
  @talker
116
120
  end
@@ -2,6 +2,7 @@ module TeamSpeak3
2
2
  module CommandParameter
3
3
  def self.encode(value)
4
4
  return unless value
5
+ value = value.to_s
5
6
 
6
7
  value.gsub!("\\", "\\\\")
7
8
  value.gsub!("/", "\/")
@@ -19,6 +20,7 @@ module TeamSpeak3
19
20
 
20
21
  def self.decode(value)
21
22
  return unless value
23
+ value = value.to_s
22
24
 
23
25
  value.gsub!("\\\\", "\\")
24
26
  value.gsub!("\/", "/")
@@ -19,14 +19,17 @@ module TeamSpeak3
19
19
  'Timeout' => @opts[:timeout] || 3,
20
20
  'Telnetmode' => false
21
21
  )
22
-
23
- @socket.waitfor(/Welcome to the TeamSpeak 3 ServerQuery interface/)
24
- rescue Net::ReadTimeout => err
22
+
23
+ @socket.waitfor("Match" => /Welcome to the TeamSpeak 3 ServerQuery interface/, "FailEOF" => true)
24
+ rescue Net::ReadTimeout
25
25
  raise TeamSpeak3::Exceptions::ServerConnectionFailed.new(@ip_address, @query_port, \
26
26
  "Timeout while waiting for TeamSpeak 3 welcome message.")
27
- rescue Net::OpenTimeout, Errno::ECONNREFUSED => err
27
+ rescue Net::OpenTimeout, Errno::ECONNREFUSED
28
28
  raise TeamSpeak3::Exceptions::ServerConnectionFailed.new(@ip_address, @query_port, \
29
29
  "Could not open connection to server at #{@ip_address}:#{@query_port}")
30
+ rescue EOFError
31
+ raise TeamSpeak3::Exceptions::ServerConnectionFailed.new(@ip_address, @query_port, \
32
+ "Server closed the connection.")
30
33
  end
31
34
 
32
35
  true
@@ -36,7 +39,7 @@ module TeamSpeak3
36
39
  verify_connection
37
40
 
38
41
  begin
39
- execute "login client_login_name=#{query_user} client_login_password=#{query_pass}"
42
+ execute :login, client_login_name: query_user, client_login_password: query_pass
40
43
  rescue TeamSpeak3::Exceptions::CommandExecutionFailed => err
41
44
  raise TeamSpeak3::Exceptions::QueryLoginFailed, err.message
42
45
  end
@@ -45,14 +48,14 @@ module TeamSpeak3
45
48
  end
46
49
 
47
50
  def select_server(virtual_server_id)
48
- execute "use sid=#{virtual_server_id}"
51
+ execute :use, sid: virtual_server_id
49
52
  @active_server = virtual_server_id
50
53
  end
51
54
 
52
55
  def virtual_servers
53
56
  server_list = []
54
57
 
55
- servers = execute "serverlist -uid -all"
58
+ servers = execute :serverlist, options: [:uid, :all]
56
59
  servers[:data].each do |server|
57
60
  server_list << TeamSpeak3::VirtualServer.new(self, server)
58
61
  end
@@ -61,26 +64,13 @@ module TeamSpeak3
61
64
  end
62
65
 
63
66
  def kick_client!(client_id, action, reason = nil)
64
- # set correct kick action
65
67
  action_id = nil
66
68
  action_id = 4 if action == :channel
67
69
  action_id = 5 if action == :server
68
70
 
69
71
  raise TeamSpeak3::Exceptions::InvalidKickAction.new(action) unless action_id
70
72
 
71
- # handle multiple client ids
72
- client_ids = ""
73
- if client_id.is_a?(Integer)
74
- client_ids = "clid=#{client_id}"
75
- elsif client_id.is_a?(Array)
76
- client_id.each { |id| client_ids += "clid=#{id}|" }
77
- client_ids = client_ids[0..-2]
78
- end
79
-
80
- # execute command
81
- command = "clientkick #{client_ids} reasonid=#{action_id}"
82
- command += " reasonmsg=#{TeamSpeak3::CommandParameter.encode(reason)}" if reason
83
- execute command
73
+ execute :clientkick, clid: client_id, reasonid: action_id, reasonmsg: reason
84
74
  end
85
75
 
86
76
  def send_message_to(target, message, target_type = :auto)
@@ -94,6 +84,11 @@ module TeamSpeak3
94
84
  target_id = target.id
95
85
  target_type_id = 2
96
86
 
87
+ select_server target.virtual_server.id
88
+ elsif target.is_a?(TeamSpeak3::Client)
89
+ target_id = target.client_id
90
+ target_type_id = 1
91
+
97
92
  select_server target.virtual_server.id
98
93
  else
99
94
  raise TeamSpeak3::Exceptions::InvalidTarget.new(target)
@@ -108,13 +103,43 @@ module TeamSpeak3
108
103
  raise TeamSpeak3::Exceptions::InvalidTargetType.new(target_type) unless target_type_id
109
104
  end
110
105
 
111
- execute "sendtextmessage target=#{target_id} targetmode=#{target_type_id} " \
112
- "msg=#{TeamSpeak3::CommandParameter.encode(message)}"
106
+ execute :sendtextmessage, target: target_id, targetmode: target_type_id, msg: message
113
107
  true
114
108
  end
115
109
 
116
- def execute(command)
117
- @socket.puts(command)
110
+ def prepare_command(command, params = {})
111
+ prepared_command = command.to_s
112
+
113
+ if params[:options]
114
+ raise ArgumentError, 'options must be an array!' unless params[:options].is_a?(Array)
115
+
116
+ params[:options].each do |option|
117
+ prepared_command += " -#{option}"
118
+ end
119
+ end
120
+
121
+ params.each do |param, value|
122
+ next if param == :options
123
+
124
+ if value.is_a?(Array)
125
+ prepared_command += ' '
126
+
127
+ value.each do |v|
128
+ prepared_command += "#{param}=#{TeamSpeak3::CommandParameter.encode(v)}|"
129
+ end
130
+
131
+ prepared_command = prepared_command[0..-2]
132
+ else
133
+ prepared_command += " #{param}=#{TeamSpeak3::CommandParameter.encode(value)}"
134
+ end
135
+ end
136
+
137
+ prepared_command
138
+ end
139
+
140
+ def execute(command, params = {})
141
+ prepared_command = prepare_command(command, params)
142
+ @socket.puts(prepared_command)
118
143
 
119
144
  # every response contains an error information. so we wait until we receive a response
120
145
  response = @socket.waitfor(/error id=.*/)
@@ -124,7 +149,7 @@ module TeamSpeak3
124
149
  raise TeamSpeak3::Exceptions::CommandExecutionFailed.new(
125
150
  response[:errors][:id],
126
151
  response[:errors][:msg],
127
- command,
152
+ prepared_command,
128
153
  )
129
154
  end
130
155
 
@@ -1,10 +1,15 @@
1
1
  require 'net/telnet'
2
2
 
3
+ module TeamSpeak3
4
+ VERSION = "0.0.4"
5
+ end
6
+
3
7
  # exceptions shall be required first
4
8
  require_relative 'exceptions.rb'
5
9
 
6
10
  # library classes ordered alphabetically
7
11
  require_relative 'channel.rb'
12
+ require_relative 'channel_collection.rb'
8
13
  require_relative 'client.rb'
9
14
  require_relative 'command_parameter.rb'
10
15
  require_relative 'virtual_server.rb'
@@ -29,23 +29,19 @@ module TeamSpeak3
29
29
  end
30
30
 
31
31
  def channels
32
- check_active_server
33
-
34
- channels_list = []
35
- channels = @server.execute "channellist -topic -flags -voice -limits -icon"
32
+ channels_list = ChannelCollection.new(self)
33
+ channels = execute :channellist, options: [:topic, :flags, :voice, :limits, :icon]
36
34
 
37
35
  channels[:data].each do |channel|
38
- channels_list << TeamSpeak3::Channel.new(self, channel)
36
+ channels_list << Channel.new(self, channel)
39
37
  end
40
38
 
41
39
  channels_list
42
40
  end
43
41
 
44
42
  def clients
45
- check_active_server
46
-
47
43
  clients_list = []
48
- clients = @server.execute "clientlist -uid -away -voice -times -groups -info -icon -country"
44
+ clients = execute :clientlist, options: [:uid, :away, :voice, :times, :groups, :info, :icon, :country]
49
45
 
50
46
  clients[:data].each do |client|
51
47
  clients_list << TeamSpeak3::Client.new(self, client)
@@ -58,6 +54,11 @@ module TeamSpeak3
58
54
  server.send_message_to(self, message)
59
55
  end
60
56
 
57
+ def execute(command, params = {})
58
+ check_active_server
59
+ @server.execute(command, params)
60
+ end
61
+
61
62
  def ==(target)
62
63
  @id == target
63
64
  end
@@ -0,0 +1,9 @@
1
+ FactoryBot.define do
2
+ factory :server, class: TeamSpeak3::Server do
3
+ ip_address '127.0.0.1'
4
+ query_port 10011
5
+ timeout 2
6
+
7
+ initialize_with { new(ip_address, query_port, timeout: timeout) }
8
+ end
9
+ end
@@ -0,0 +1,88 @@
1
+ require_relative 'spec_helper.rb'
2
+ require 'socket'
3
+
4
+ describe TeamSpeak3::Server do
5
+ describe '#initialize' do
6
+ context 'attr_reader' do
7
+ let(:server) { FactoryBot.build(:server) }
8
+
9
+ it { expect(server.ip_address).to eq('127.0.0.1') }
10
+ it { expect(server.query_port).to eq(10011) }
11
+ end
12
+ end
13
+
14
+ describe '#connect' do
15
+ let(:query_port) { rand(50000..60000) }
16
+ let(:server) { FactoryBot.build(:server, ip_address: '127.0.0.1', query_port: query_port) }
17
+
18
+ describe 'telnet connection' do
19
+ context 'for a valid TeamSpeak 3 server' do
20
+ before do
21
+ # spawn a tcp server for connection tests
22
+ Thread.new(query_port) do |query_port|
23
+ tcp_server = TCPServer.new('127.0.0.1', query_port)
24
+ client = tcp_server.accept
25
+ client.puts "Welcome to the TeamSpeak 3 ServerQuery interface"
26
+ sleep 3
27
+ client.close
28
+ tcp_server.close
29
+ end
30
+
31
+ # it takes a moment till the server has spawned
32
+ sleep 2
33
+ end
34
+
35
+ it { expect { server.connect }.to_not raise_error }
36
+ end
37
+
38
+ context 'for a non-TeamSpeak 3 server' do
39
+ before do
40
+ # spawn a tcp server for connection tests
41
+ Thread.new(query_port) do |query_port|
42
+ tcp_server = TCPServer.new('127.0.0.1', query_port)
43
+ client = tcp_server.accept
44
+ client.puts "I'm not a TeamSpeak 3 server"
45
+ sleep 3
46
+ client.close
47
+ tcp_server.close
48
+ end
49
+
50
+ # it takes a moment till the server has spawned
51
+ sleep 2
52
+ end
53
+
54
+ it { expect { server.connect }.to raise_error(TeamSpeak3::Exceptions::ServerConnectionFailed, /welcome message/) }
55
+ end
56
+ end
57
+ end
58
+
59
+ describe '#prepare_command' do
60
+ let(:server) { FactoryBot.build(:server) }
61
+
62
+ context 'with options' do
63
+ it { expect(server.prepare_command(:clientlist, options: [:uid, :away, :voice])).to eq('clientlist -uid -away -voice') }
64
+ end
65
+
66
+ context 'with parameters' do
67
+ it { expect(server.prepare_command(:clientlist, argument1: 'hello', argument2: 'test')).to \
68
+ eq('clientlist argument1=hello argument2=test') }
69
+ end
70
+
71
+ context 'with parameters and options' do
72
+ it { expect(server.prepare_command(:clientlist, argument1: 'hello', argument2: 'test', options: [:uid, :flags])).to \
73
+ eq('clientlist -uid -flags argument1=hello argument2=test') }
74
+ end
75
+
76
+ context 'with arrays as parameters' do
77
+ it { expect(server.prepare_command(:clientkick, clid: [1,2,3], argument2: 'test')).to \
78
+ eq('clientkick clid=1|clid=2|clid=3 argument2=test') }
79
+ end
80
+
81
+ context 'argument encoding' do
82
+ it { expect(server.prepare_command(:clientkick, argument1: 'I need | encoding!!')).to \
83
+ eq("clientkick argument1=I\\sneed\\s\\p\\sencoding!!") }
84
+ it { expect(server.prepare_command(:clientkick, argument: ['I need | encoding!!', 'me | too!!'])).to \
85
+ eq("clientkick argument=I\\sneed\\s\\p\\sencoding!!|argument=me\\s\\p\\stoo!!") }
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,10 @@
1
+ require_relative '../lib/teamspeak3.rb'
2
+ require 'factory_bot'
3
+
4
+ RSpec.configure do |config|
5
+ config.include FactoryBot::Syntax::Methods
6
+
7
+ config.before(:suite) do
8
+ FactoryBot.find_definitions
9
+ end
10
+ end
metadata CHANGED
@@ -1,22 +1,86 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teamspeak3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manuel Schnitzer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-05 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2018-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net-telnet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.1.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.1.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.7'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.7.0
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.7'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 3.7.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: factory_bot
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '4.8'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 4.8.2
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '4.8'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 4.8.2
13
73
  description: An OOP library to query and manage TeamSpeak 3 servers in Ruby.
14
74
  email: webmaster@mschnitzer.de
15
75
  executables: []
16
76
  extensions: []
17
77
  extra_rdoc_files: []
18
78
  files:
79
+ - ".rspec"
80
+ - CHANGELOG.md
81
+ - README.md
19
82
  - lib/channel.rb
83
+ - lib/channel_collection.rb
20
84
  - lib/client.rb
21
85
  - lib/command_parameter.rb
22
86
  - lib/exceptions.rb
@@ -32,6 +96,9 @@ files:
32
96
  - lib/server_response.rb
33
97
  - lib/teamspeak3.rb
34
98
  - lib/virtual_server.rb
99
+ - spec/factories/server.rb
100
+ - spec/server_spec.rb
101
+ - spec/spec_helper.rb
35
102
  homepage: https://github.com/mschnitzer/teamspeak3
36
103
  licenses:
37
104
  - MIT