minestat 3.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +6 -0
  3. data/ReadMe.md +9 -5
  4. data/example.rb +1 -1
  5. data/lib/minestat.rb +84 -54
  6. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82717df75838b6ad324792fe9a77d2546de09ac67d4f29df16d9d5ccdadc7b86
4
- data.tar.gz: ebc141d36e1e8873794c1c1f6945b77bdb3578a28ab04098b939725ba2af18a1
3
+ metadata.gz: e8a29b7c1a834e40e6a63b451abc0cd67018ca48b8efcdcd04a6ca365390cec0
4
+ data.tar.gz: 609d3ed8ccfdff65d6c317b25066012eeafb7e206dd347923088fe4108588add
5
5
  SHA512:
6
- metadata.gz: 1813f254761c46b13d6137fbe992e3deca495ecc3d02d134382970f47a968014806e2076f04ea7258fca05f27b88ae7aa0087de7f3ea1cc137d260694dccbc28
7
- data.tar.gz: 04c3aa462ab0ae42d822aa9b67290809c14a9789d7a9adc42a6c7c32bedfb6340e13ed9dc4528577fa1a176fe856ff43f470108acafec21eba5d996d42ccc8db
6
+ metadata.gz: 5b27f9e97df7fc7f2f38d0d18ae1f4c14015845ca0590cc8a33d269642697d41001c130ba36b6c7e0c39a5e39020b28b64bc02b78333ecfd1c3047a430d43555
7
+ data.tar.gz: f7e487a9a821c8b2aa83b8120c55eeb08b7229797bf6f62aff18937c4875db238ad88e3b6be08e6948303b79f74494d5ae60725fb9917d58729535d57aa33175
data/ChangeLog.md CHANGED
@@ -1,5 +1,11 @@
1
+ ## 3.0.1 (February 5, 2023)
2
+ - Added configurable DNS SRV resolution
3
+ - Added request type that attempts all SLP protocols
4
+ - Improved debug messages
5
+
1
6
  ## 3.0.0 (January 31, 2023)
2
7
  - Added UT3/GS4 query support
8
+ - Added debug mode
3
9
  - Refactored code
4
10
  - Added YARD documentation
5
11
 
data/ReadMe.md CHANGED
@@ -18,7 +18,7 @@ To install the gem: `gem install minestat`
18
18
  ```ruby
19
19
  require 'minestat'
20
20
 
21
- ms = MineStat.new("minecraft.frag.land", 25565)
21
+ ms = MineStat.new("frag.land")
22
22
  puts "Minecraft server status of #{ms.address} on port #{ms.port}:"
23
23
  if ms.online
24
24
  puts "Server is online running version #{ms.version} with #{ms.current_players} out of #{ms.max_players} players."
@@ -36,24 +36,28 @@ end
36
36
 
37
37
  To simply connect to an address:
38
38
  ```ruby
39
- ms = MineStat.new("minecraft.frag.land")
39
+ ms = MineStat.new("frag.land")
40
40
  ```
41
41
  Connect to an address on a certain TCP or UDP port:
42
42
  ```ruby
43
- ms = MineStat.new("minecraft.frag.land", 25567)
43
+ ms = MineStat.new("frag.land", 25565)
44
44
  ```
45
45
  Same as above example and additionally includes a timeout in seconds:
46
46
  ```ruby
47
- ms = MineStat.new("minecraft.frag.land", 25567, 3)
47
+ ms = MineStat.new("frag.land", 25565, 3)
48
48
  ```
49
49
  Same as above example and additionally includes an explicit protocol to use:
50
50
  ```ruby
51
- ms = MineStat.new("minecraft.frag.land", 25567, 3, MineStat::Request::QUERY)
51
+ ms = MineStat.new("frag.land", 25565, 3, MineStat::Request::QUERY)
52
52
  ```
53
53
  Connect to a Bedrock server and enable debug mode:
54
54
  ```ruby
55
55
  ms = MineStat.new("minecraft.frag.land", 19132, 3, MineStat::Request::BEDROCK, true)
56
56
  ```
57
+ Attempt all SLP protocols, disable debug mode, and disable DNS SRV resolution:
58
+ ```ruby
59
+ ms = MineStat.new("minecraft.frag.land", 25565, 3, MineStat::Request::SLP, false, false)
60
+ ```
57
61
 
58
62
  ### Support
59
63
  * Discord: https://discord.frag.land
data/example.rb CHANGED
@@ -2,7 +2,7 @@ require 'minestat'
2
2
 
3
3
  # Below is an example using the MineStat class.
4
4
  # If server is offline, other instance members will be nil.
5
- ms = MineStat.new("minecraft.frag.land")
5
+ ms = MineStat.new("frag.land")
6
6
  # Bedrock/Pocket Edition explicit query example with debug enabled
7
7
  #ms = MineStat.new("minecraft.frag.land", 19132, 5, MineStat::Request::BEDROCK, true)
8
8
  puts "Minecraft server status of #{ms.address} on port #{ms.port}:"
data/lib/minestat.rb CHANGED
@@ -27,7 +27,7 @@ require 'timeout'
27
27
  # Provides a Ruby interface for polling the status of Minecraft servers
28
28
  class MineStat
29
29
  # MineStat version
30
- VERSION = "3.0.0"
30
+ VERSION = "3.0.1"
31
31
 
32
32
  # Number of values expected from server
33
33
  NUM_FIELDS = 6
@@ -116,6 +116,10 @@ class MineStat
116
116
 
117
117
  # Unreal Tournament 3/GameSpy 4 query
118
118
  QUERY = 5
119
+
120
+ # SLP only
121
+ # @since 3.0.1
122
+ SLP = 6
119
123
  end
120
124
 
121
125
  # Instantiates a MineStat object and polls the specified server for information
@@ -126,59 +130,60 @@ class MineStat
126
130
  # @param debug [Boolean] Enable or disable error output
127
131
  # @return [MineStat] A MineStat object
128
132
  # @example Simply connect to an address
129
- # ms = MineStat.new("minecraft.frag.land")
133
+ # ms = MineStat.new("frag.land")
130
134
  # @example Connect to an address on a certain TCP or UDP port
131
- # ms = MineStat.new("minecraft.frag.land", 25567)
135
+ # ms = MineStat.new("frag.land", 25565)
132
136
  # @example Same as above example and additionally includes a timeout in seconds
133
- # ms = MineStat.new("minecraft.frag.land", 25567, 3)
137
+ # ms = MineStat.new("frag.land", 25565, 3)
134
138
  # @example Same as above example and additionally includes an explicit protocol to use
135
- # ms = MineStat.new("minecraft.frag.land", 25567, 3, MineStat::Request::QUERY)
139
+ # ms = MineStat.new("frag.land", 25565, 3, MineStat::Request::QUERY)
136
140
  # @example Connect to a Bedrock server and enable debug mode
137
141
  # ms = MineStat.new("minecraft.frag.land", 19132, 3, MineStat::Request::BEDROCK, true)
138
- def initialize(address, port = DEFAULT_TCP_PORT, timeout = DEFAULT_TIMEOUT, request_type = Request::NONE, debug = false)
139
- @address = address # address of server
140
- @port = port # TCP/UDP port of server
141
- @online # online or offline?
142
- @version # server version
143
- @mode # game mode (Bedrock/Pocket Edition only)
144
- @motd # message of the day
145
- @stripped_motd # message of the day without formatting
146
- @current_players # current number of players online
147
- @max_players # maximum player capacity
148
- @player_list # list of players (UT3/GS4 query only)
149
- @plugin_list # list of plugins (UT3/GS4 query only)
150
- @protocol # protocol level
151
- @json_data # JSON data for 1.7 queries
152
- @favicon_b64 # base64-encoded favicon possibly contained in JSON 1.7 responses
153
- @favicon # decoded favicon data
154
- @latency # ping time to server in milliseconds
155
- @timeout = timeout # TCP/UDP timeout
156
- @server # server socket
157
- @request_type # protocol version
158
- @connection_status # status of connection ("Success", "Fail", "Timeout", or "Unknown")
159
- @try_all = false # try all protocols?
160
- @debug = debug # debug mode
142
+ # @example Attempt all SLP protocols, disable debug mode, and disable DNS SRV resolution
143
+ # ms = MineStat.new("minecraft.frag.land", 25565, 3, MineStat::Request::SLP, false, false)
144
+ def initialize(address, port = DEFAULT_TCP_PORT, timeout = DEFAULT_TIMEOUT, request_type = Request::NONE, debug = false, srv_enabled = true)
145
+ @address = address # address of server
146
+ @port = port # TCP/UDP port of server
147
+ @srv_address # server address from DNS SRV record
148
+ @srv_port # server TCP port from DNS SRV record
149
+ @online # online or offline?
150
+ @version # server version
151
+ @mode # game mode (Bedrock/Pocket Edition only)
152
+ @motd # message of the day
153
+ @stripped_motd # message of the day without formatting
154
+ @current_players # current number of players online
155
+ @max_players # maximum player capacity
156
+ @player_list # list of players (UT3/GS4 query only)
157
+ @plugin_list # list of plugins (UT3/GS4 query only)
158
+ @protocol # protocol level
159
+ @json_data # JSON data for 1.7 queries
160
+ @favicon_b64 # base64-encoded favicon possibly contained in JSON 1.7 responses
161
+ @favicon # decoded favicon data
162
+ @latency # ping time to server in milliseconds
163
+ @timeout = timeout # TCP/UDP timeout
164
+ @server # server socket
165
+ @request_type # protocol version
166
+ @connection_status # status of connection ("Success", "Fail", "Timeout", or "Unknown")
167
+ @try_all = false # try all protocols?
168
+ @debug = debug # debug mode
169
+ @srv_enabled = srv_enabled # enable SRV resolution?
161
170
 
162
171
  @try_all = true if request_type == Request::NONE
163
- resolve_srv(address, port)
172
+ resolve_srv() if @srv_enabled
164
173
  set_connection_status(attempt_protocols(request_type))
165
174
  end
166
175
 
167
- # Attempts to resolve SRV records
168
- # @param address [String] Minecraft server address
169
- # @param port [Integer] Minecraft server TCP or UDP port
176
+ # Attempts to resolve DNS SRV records
170
177
  # @return [Boolean] Whether or not SRV resolution was successful
171
178
  # @since 2.3.0
172
- def resolve_srv(address, port)
179
+ def resolve_srv()
173
180
  begin
174
181
  resolver = Resolv::DNS.new
175
182
  res = resolver.getresource("_minecraft._tcp.#{@address}", Resolv::DNS::Resource::IN::SRV)
176
- @address = res.target.to_s # SRV target
177
- @port = res.port.to_i # SRV port
178
- rescue => exception # primarily catch Resolv::ResolvError and revert if unable to resolve SRV record(s)
179
- $stderr.puts exception if @debug
180
- @address = address
181
- @port = port
183
+ @srv_address = res.target.to_s # SRV target
184
+ @srv_port = res.port.to_i # SRV port
185
+ rescue => exception # primarily catch Resolv::ResolvError and revert if unable to resolve SRV record(s)
186
+ $stderr.puts "resolve_srv(): #{exception}" if @debug
182
187
  return false
183
188
  end
184
189
  return true
@@ -222,6 +227,7 @@ class MineStat
222
227
  unless retval == Retval::CONNFAIL
223
228
  retval = json_request()
224
229
  end
230
+ return retval if request_type == Request::SLP
225
231
  # Bedrock/Pocket Edition
226
232
  unless @online || retval == Retval::SUCCESS
227
233
  retval = bedrock_request()
@@ -275,13 +281,18 @@ class MineStat
275
281
  @server.connect(@address, @port)
276
282
  else
277
283
  start_time = Time.now
278
- @server = TCPSocket.new(@address, @port)
284
+ if @srv_enabled
285
+ @server = TCPSocket.new(@srv_address, @srv_port)
286
+ else
287
+ @server = TCPSocket.new(@address, @port)
288
+ end
279
289
  end
280
290
  @latency = ((Time.now - start_time) * 1000).round
281
291
  rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
292
+ $stderr.puts "connect(): Host unreachable or connection refused" if @debug
282
293
  return Retval::CONNFAIL
283
294
  rescue => exception
284
- $stderr.puts exception if @debug
295
+ $stderr.puts "connect(): #{exception}" if @debug
285
296
  return Retval::UNKNOWN
286
297
  end
287
298
  return Retval::SUCCESS
@@ -322,7 +333,7 @@ class MineStat
322
333
  end
323
334
  end
324
335
  rescue => exception
325
- $stderr.puts exception if @debug
336
+ $stderr.puts "check_response(): #{exception}" if @debug
326
337
  return nil, Retval::UNKNOWN
327
338
  end
328
339
  retval = Retval::UNKNOWN if data == nil || data.empty?
@@ -347,7 +358,7 @@ class MineStat
347
358
  if server_info != nil && server_info.length >= NUM_FIELDS_BETA
348
359
  @version = ">=1.8b/1.3" # since server does not return version, set it
349
360
  @motd = server_info[0]
350
- strip_motd
361
+ strip_motd()
351
362
  @current_players = server_info[1].to_i
352
363
  @max_players = server_info[2].to_i
353
364
  @online = true
@@ -360,7 +371,7 @@ class MineStat
360
371
  @version = "#{server_info[3]} #{server_info[7]} (#{server_info[0]})"
361
372
  @mode = server_info[8]
362
373
  @motd = server_info[1]
363
- strip_motd
374
+ strip_motd()
364
375
  @current_players = server_info[4].to_i
365
376
  @max_players = server_info[5].to_i
366
377
  @online = true
@@ -373,7 +384,7 @@ class MineStat
373
384
  server_info = Hash[*server_info[0].split(delimiter).flatten(1)]
374
385
  @version = server_info["version"]
375
386
  @motd = server_info["hostname"]
376
- strip_motd
387
+ strip_motd()
377
388
  @current_players = server_info["numplayers"].to_i
378
389
  @max_players = server_info["maxplayers"].to_i
379
390
  unless server_info["plugins"].nil? || server_info["plugins"].empty?
@@ -392,7 +403,7 @@ class MineStat
392
403
  @protocol = server_info[1].to_i # contains the protocol version (51 for 1.9 or 78 for 1.6.4 for example)
393
404
  @version = server_info[2]
394
405
  @motd = server_info[3]
395
- strip_motd
406
+ strip_motd()
396
407
  @current_players = server_info[4].to_i
397
408
  @max_players = server_info[5].to_i
398
409
  @online = true
@@ -429,9 +440,10 @@ class MineStat
429
440
  retval = parse_data("\u00A7", true) # section symbol
430
441
  end
431
442
  rescue Timeout::Error
443
+ $stderr.puts "beta_request(): Connection timed out" if @debug
432
444
  return Retval::TIMEOUT
433
445
  rescue => exception
434
- $stderr.puts exception if @debug
446
+ $stderr.puts "beta_request(): #{exception}" if @debug
435
447
  return Retval::UNKNOWN
436
448
  end
437
449
  if retval == Retval::SUCCESS
@@ -474,9 +486,10 @@ class MineStat
474
486
  retval = parse_data("\x00") # null
475
487
  end
476
488
  rescue Timeout::Error
489
+ $stderr.puts "legacy_request(): Connection timed out" if @debug
477
490
  return Retval::TIMEOUT
478
491
  rescue => exception
479
- $stderr.puts exception if @debug
492
+ $stderr.puts "legacy_request(): #{exception}" if @debug
480
493
  return Retval::UNKNOWN
481
494
  end
482
495
  if retval == Retval::SUCCESS
@@ -535,9 +548,10 @@ class MineStat
535
548
  retval = parse_data("\x00") # null
536
549
  end
537
550
  rescue Timeout::Error
551
+ $stderr.puts "extended_legacy_request(): Connection timed out" if @debug
538
552
  return Retval::TIMEOUT
539
553
  rescue => exception
540
- $stderr.puts exception if @debug
554
+ $stderr.puts "extended_legacy_request(): #{exception}" if @debug
541
555
  return Retval::UNKNOWN
542
556
  end
543
557
  if retval == Retval::SUCCESS
@@ -596,7 +610,7 @@ class MineStat
596
610
  @protocol = json_data['version']['protocol'].to_i
597
611
  @version = json_data['version']['name']
598
612
  @motd = json_data['description']
599
- strip_motd
613
+ strip_motd()
600
614
  @current_players = json_data['players']['online'].to_i
601
615
  @max_players = json_data['players']['max'].to_i
602
616
  @favicon_b64 = json_data['favicon']
@@ -611,11 +625,13 @@ class MineStat
611
625
  end
612
626
  end
613
627
  rescue Timeout::Error
628
+ $stderr.puts "json_request(): Connection timed out" if @debug
614
629
  return Retval::TIMEOUT
615
630
  rescue JSON::ParserError
631
+ $stderr.puts "json_request(): JSON parse error" if @debug
616
632
  return Retval::UNKNOWN
617
633
  rescue => exception
618
- $stderr.puts exception if @debug
634
+ $stderr.puts "json_request(): #{exception}" if @debug
619
635
  return Retval::UNKNOWN
620
636
  end
621
637
  if retval == Retval::SUCCESS
@@ -640,7 +656,7 @@ class MineStat
640
656
  break if json_data.length >= json_len
641
657
  end
642
658
  rescue => exception
643
- $stderr.puts exception if @debug
659
+ $stderr.puts "recv_json(): #{exception}" if @debug
644
660
  end
645
661
  return json_data
646
662
  end
@@ -711,9 +727,10 @@ class MineStat
711
727
  retval = parse_data("\x3B") # semicolon
712
728
  end
713
729
  rescue Timeout::Error
730
+ $stderr.puts "bedrock_request(): Connection timed out" if @debug
714
731
  return Retval::TIMEOUT
715
732
  rescue => exception
716
- $stderr.puts exception if @debug
733
+ $stderr.puts "bedrock_request(): #{exception}" if @debug
717
734
  return Retval::UNKNOWN
718
735
  end
719
736
  if retval == Retval::SUCCESS
@@ -777,9 +794,10 @@ class MineStat
777
794
  retval = parse_data("\x00") # null
778
795
  end
779
796
  rescue Timeout::Error
797
+ $stderr.puts "query_request(): Connection timed out" if @debug
780
798
  return Retval::TIMEOUT
781
799
  rescue => exception
782
- $stderr.puts exception if @debug
800
+ $stderr.puts "query_request(): #{exception}" if @debug
783
801
  return Retval::UNKNOWN
784
802
  end
785
803
  if retval == Retval::SUCCESS
@@ -795,6 +813,14 @@ class MineStat
795
813
  # Port (TCP or UDP) of the Minecraft server
796
814
  attr_reader :port
797
815
 
816
+ # Address of the Minecraft server from a DNS SRV record
817
+ # @since 3.0.1
818
+ attr_reader :srv_address
819
+
820
+ # TCP port of the Minecraft server from a DNS SRV record
821
+ # @since 3.0.1
822
+ attr_reader :srv_port
823
+
798
824
  # Whether or not the Minecraft server is online
799
825
  attr_reader :online
800
826
 
@@ -872,4 +898,8 @@ class MineStat
872
898
  # Whether or not debug mode is enabled
873
899
  # @since 3.0.0
874
900
  attr_reader :debug
901
+
902
+ # Whether or not DNS SRV resolution is enabled
903
+ # @since 3.0.1
904
+ attr_reader :srv_enabled
875
905
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minestat
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lloyd Dilley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-01 00:00:00.000000000 Z
11
+ date: 2023-02-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: MineStat polls Minecraft server data such as version, motd, current players,
14
14
  and max players.