qwtf_discord_bot 1.0.8 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +27 -24
- data/README.md +11 -13
- data/exe/qwtf_discord_bot +4 -10
- data/lib/player.rb +1 -1
- data/lib/qstat_request.rb +10 -6
- data/lib/qwtf_discord_bot.rb +12 -10
- data/lib/qwtf_discord_bot/qwtf_discord_bot_server.rb +42 -8
- data/lib/qwtf_discord_bot/qwtf_discord_bot_watcher.rb +12 -9
- data/lib/qwtf_discord_bot/version.rb +1 -1
- data/qwtf_discord_bot.gemspec +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b27a7b9906ac7f444707b27c3f59accc8df4c91dfd5ce27d1f0db727eb0aba1
|
4
|
+
data.tar.gz: 341f084c7be0fd7a3305028dc6548d9723614e350f1e203e5e18506d0e17b422
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88d5dbf22c9235b956b0b63635586f157222ab175350af41ff4048221ee1dab5d3a048468e4350ac3419fa6ff566c5b22c62a5ab4834550267bd3ea43e6bf9eb
|
7
|
+
data.tar.gz: b056461ec34f9889d9eac15bdb03ab5e9d29f9250c294616e83e79f818c729fe23707b19b68352294b7c9843656929a60782fd5f38870191e55fdfef918b10d0
|
data/Gemfile.lock
CHANGED
@@ -1,53 +1,56 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
qwtf_discord_bot (1.0.
|
5
|
-
discordrb
|
6
|
-
thor
|
4
|
+
qwtf_discord_bot (1.0.8)
|
5
|
+
discordrb (~> 3.3)
|
6
|
+
thor (~> 0.20)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (5.2.
|
11
|
+
activesupport (5.2.3)
|
12
12
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
13
|
i18n (>= 0.7, < 2)
|
14
14
|
minitest (~> 5.1)
|
15
15
|
tzinfo (~> 1.1)
|
16
16
|
coderay (1.1.2)
|
17
|
-
concurrent-ruby (1.
|
17
|
+
concurrent-ruby (1.1.5)
|
18
18
|
diff-lcs (1.3)
|
19
|
-
discordrb (3.
|
20
|
-
discordrb-webhooks (~> 3.
|
19
|
+
discordrb (3.3.0)
|
20
|
+
discordrb-webhooks (~> 3.3.0)
|
21
|
+
ffi (>= 1.9.24)
|
21
22
|
opus-ruby
|
22
23
|
rbnacl (~> 3.4.0)
|
23
|
-
rest-client
|
24
|
+
rest-client (>= 2.1.0.rc1)
|
24
25
|
websocket-client-simple (>= 0.3.0)
|
25
|
-
discordrb-webhooks (3.
|
26
|
-
rest-client
|
26
|
+
discordrb-webhooks (3.3.0)
|
27
|
+
rest-client (>= 2.1.0.rc1)
|
27
28
|
domain_name (0.5.20180417)
|
28
29
|
unf (>= 0.0.5, < 1.0.0)
|
29
30
|
event_emitter (0.2.6)
|
30
|
-
factory_bot (
|
31
|
-
activesupport (>=
|
32
|
-
ffi (1.
|
31
|
+
factory_bot (5.0.2)
|
32
|
+
activesupport (>= 4.2.0)
|
33
|
+
ffi (1.11.1)
|
34
|
+
http-accept (1.7.0)
|
33
35
|
http-cookie (1.0.3)
|
34
36
|
domain_name (~> 0.5)
|
35
|
-
i18n (1.
|
37
|
+
i18n (1.6.0)
|
36
38
|
concurrent-ruby (~> 1.0)
|
37
|
-
method_source (0.9.
|
39
|
+
method_source (0.9.2)
|
38
40
|
mime-types (3.2.2)
|
39
41
|
mime-types-data (~> 3.2015)
|
40
|
-
mime-types-data (3.
|
42
|
+
mime-types-data (3.2019.0331)
|
41
43
|
minitest (5.11.3)
|
42
44
|
netrc (0.11.0)
|
43
45
|
opus-ruby (1.0.1)
|
44
46
|
ffi
|
45
|
-
pry (0.
|
47
|
+
pry (0.12.2)
|
46
48
|
coderay (~> 1.1.0)
|
47
49
|
method_source (~> 0.9.0)
|
48
50
|
rbnacl (3.4.0)
|
49
51
|
ffi
|
50
|
-
rest-client (2.0.
|
52
|
+
rest-client (2.1.0.rc1)
|
53
|
+
http-accept (>= 1.7.0, < 2.0)
|
51
54
|
http-cookie (>= 1.0.2, < 2.0)
|
52
55
|
mime-types (>= 1.16, < 4.0)
|
53
56
|
netrc (~> 0.8)
|
@@ -55,22 +58,22 @@ GEM
|
|
55
58
|
rspec-core (~> 3.8.0)
|
56
59
|
rspec-expectations (~> 3.8.0)
|
57
60
|
rspec-mocks (~> 3.8.0)
|
58
|
-
rspec-core (3.8.
|
61
|
+
rspec-core (3.8.1)
|
59
62
|
rspec-support (~> 3.8.0)
|
60
|
-
rspec-expectations (3.8.
|
63
|
+
rspec-expectations (3.8.4)
|
61
64
|
diff-lcs (>= 1.2.0, < 2.0)
|
62
65
|
rspec-support (~> 3.8.0)
|
63
|
-
rspec-mocks (3.8.
|
66
|
+
rspec-mocks (3.8.1)
|
64
67
|
diff-lcs (>= 1.2.0, < 2.0)
|
65
68
|
rspec-support (~> 3.8.0)
|
66
|
-
rspec-support (3.8.
|
67
|
-
thor (0.20.
|
69
|
+
rspec-support (3.8.2)
|
70
|
+
thor (0.20.3)
|
68
71
|
thread_safe (0.3.6)
|
69
72
|
tzinfo (1.2.5)
|
70
73
|
thread_safe (~> 0.1)
|
71
74
|
unf (0.1.4)
|
72
75
|
unf_ext
|
73
|
-
unf_ext (0.0.7.
|
76
|
+
unf_ext (0.0.7.6)
|
74
77
|
websocket (1.2.8)
|
75
78
|
websocket-client-simple (0.3.0)
|
76
79
|
event_emitter
|
data/README.md
CHANGED
@@ -25,16 +25,16 @@ Edit the `.env.example` file, update with your bot's `client_id` and `token` and
|
|
25
25
|
|
26
26
|
### List commands
|
27
27
|
|
28
|
-
$ bundle exec exe/qwtf-discord-bot
|
28
|
+
$ bundle exec exe/qwtf-discord-bot help
|
29
29
|
|
30
30
|
There are two features:
|
31
31
|
|
32
32
|
|
33
33
|
### Server
|
34
34
|
|
35
|
-
This responds to `!
|
35
|
+
This responds to `!servers` messages by providing information about your game
|
36
36
|
server. Defaults to the hostname command line argument, but will accept a
|
37
|
-
hostname from the user. I.E. `!server fortressone.
|
37
|
+
hostname from the user. I.E. `!server fortressone.org`
|
38
38
|
|
39
39
|
![screenshot of bot responding to !server command](server_screenshot.png)
|
40
40
|
|
@@ -43,15 +43,15 @@ Usage:
|
|
43
43
|
qwtf_discord_bot server
|
44
44
|
|
45
45
|
Options:
|
46
|
-
[--
|
47
|
-
|
48
|
-
[--port=N]
|
49
|
-
# Default: 27500
|
46
|
+
[--endpoints=one two three]
|
47
|
+
# Default: ["localhost:27500"]
|
50
48
|
```
|
51
49
|
|
52
50
|
E.G.
|
53
51
|
|
54
|
-
$
|
52
|
+
$ qwtf-discord-bot server --endpoints \
|
53
|
+
sydney.fortressone.org:27500 \
|
54
|
+
sydney.fortressone.org:27501
|
55
55
|
|
56
56
|
|
57
57
|
### Watcher
|
@@ -67,15 +67,13 @@ Usage:
|
|
67
67
|
qwtf_discord_bot watcher
|
68
68
|
|
69
69
|
Options:
|
70
|
-
[--
|
71
|
-
|
72
|
-
[--port=N]
|
73
|
-
# Default: 27500
|
70
|
+
[--endpoints=one two three]
|
71
|
+
# Default: ["localhost:27500"]
|
74
72
|
```
|
75
73
|
|
76
74
|
E.G.
|
77
75
|
|
78
|
-
$ bundle exec exe/qwtf-discord-bot watcher --
|
76
|
+
$ bundle exec exe/qwtf-discord-bot watcher --endpoints sydney.fortressone.org:27501
|
79
77
|
|
80
78
|
|
81
79
|
## License
|
data/exe/qwtf_discord_bot
CHANGED
@@ -9,22 +9,16 @@ class QwtfDiscordBotExe < Thor
|
|
9
9
|
end
|
10
10
|
|
11
11
|
desc 'server', 'Responds to `!server` with server information'
|
12
|
-
method_option :
|
13
|
-
method_option :port, type: :numeric, alias: '-p', default: 27500
|
12
|
+
method_option :endpoints, type: :array, alias: '-e', default: ['localhost:27500']
|
14
13
|
def server
|
15
|
-
|
16
|
-
port = options['port']
|
17
|
-
server_bot = QwtfDiscordBotServer.new(hostname: hostname, port: port)
|
14
|
+
server_bot = QwtfDiscordBotServer.new(options[:endpoints])
|
18
15
|
server_bot.run
|
19
16
|
end
|
20
17
|
|
21
18
|
desc 'watcher', 'Watches server and accounces when a player joins'
|
22
|
-
method_option :
|
23
|
-
method_option :port, type: :numeric, alias: '-p', default: 27500
|
19
|
+
method_option :endpoints, type: :array, alias: '-e', default: ['localhost:27500']
|
24
20
|
def watcher
|
25
|
-
|
26
|
-
port = options['port']
|
27
|
-
watcher_bot = QwtfDiscordBotWatcher.new(hostname: hostname, port: port)
|
21
|
+
watcher_bot = QwtfDiscordBotWatcher.new(options[:endpoints])
|
28
22
|
watcher_bot.run
|
29
23
|
end
|
30
24
|
end
|
data/lib/player.rb
CHANGED
data/lib/qstat_request.rb
CHANGED
@@ -28,8 +28,8 @@ class QstatRequest
|
|
28
28
|
|
29
29
|
def server_summary
|
30
30
|
return "#{@endpoint} isn't responding" unless game_map
|
31
|
-
return "#{@endpoint} | #{game_map} | #{numplayers}/#{maxplayers}" unless has_spectators?
|
32
|
-
"#{@endpoint} | #{game_map} | #{numplayers}/#{maxplayers} players | #{numspectators}/#{maxspectators} spectators"
|
31
|
+
return "#{name} | #{@endpoint} | #{game_map} | #{numplayers}/#{maxplayers}" unless has_spectators?
|
32
|
+
"#{name} | #{@endpoint} | #{game_map} | #{numplayers}/#{maxplayers} players | #{numspectators}/#{maxspectators} spectators"
|
33
33
|
end
|
34
34
|
|
35
35
|
def is_empty?
|
@@ -40,16 +40,16 @@ class QstatRequest
|
|
40
40
|
players.map(&:name)
|
41
41
|
end
|
42
42
|
|
43
|
+
def has_players?
|
44
|
+
numplayers && numplayers > 0
|
45
|
+
end
|
46
|
+
|
43
47
|
private
|
44
48
|
|
45
49
|
def has_spectators?
|
46
50
|
numspectators && numspectators > 0
|
47
51
|
end
|
48
52
|
|
49
|
-
def has_players?
|
50
|
-
numplayers && numplayers > 0
|
51
|
-
end
|
52
|
-
|
53
53
|
def teams
|
54
54
|
@teams ||= build_roster
|
55
55
|
end
|
@@ -66,6 +66,10 @@ class QstatRequest
|
|
66
66
|
players.sort_by { |player| player.team.number }.map(&:to_row).join("\n")
|
67
67
|
end
|
68
68
|
|
69
|
+
def name
|
70
|
+
data["name"]
|
71
|
+
end
|
72
|
+
|
69
73
|
def address
|
70
74
|
data["address"]
|
71
75
|
end
|
data/lib/qwtf_discord_bot.rb
CHANGED
@@ -10,19 +10,21 @@ require 'emoji'
|
|
10
10
|
require 'roster'
|
11
11
|
|
12
12
|
class QwtfDiscordBot
|
13
|
+
ENV_VARS = [
|
14
|
+
'QWTF_DISCORD_BOT_TOKEN',
|
15
|
+
'QWTF_DISCORD_BOT_CLIENT_ID',
|
16
|
+
'QWTF_DISCORD_BOT_CHANNEL_ID'
|
17
|
+
]
|
18
|
+
|
19
|
+
if ENV_VARS.any? { |var| !ENV.key?(var) }
|
20
|
+
raise "Environment variables not configured"
|
21
|
+
end
|
22
|
+
|
13
23
|
TOKEN = ENV['QWTF_DISCORD_BOT_TOKEN'].strip
|
14
24
|
CLIENT_ID = ENV['QWTF_DISCORD_BOT_CLIENT_ID'].strip
|
15
25
|
CHANNEL_ID = ENV['QWTF_DISCORD_BOT_CHANNEL_ID'].strip
|
16
26
|
|
17
|
-
def initialize(
|
18
|
-
@
|
19
|
-
@port = port
|
20
|
-
end
|
21
|
-
|
22
|
-
def endpoint
|
23
|
-
@endpoint ||= begin
|
24
|
-
return @hostname if @port == 27500
|
25
|
-
[@hostname, @port].join(':')
|
26
|
-
end
|
27
|
+
def initialize(endpoints)
|
28
|
+
@endpoints = endpoints
|
27
29
|
end
|
28
30
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'pry'
|
1
2
|
class QwtfDiscordBotServer < QwtfDiscordBot
|
2
3
|
def run
|
3
4
|
bot = Discordrb::Commands::CommandBot.new(
|
@@ -7,16 +8,49 @@ class QwtfDiscordBotServer < QwtfDiscordBot
|
|
7
8
|
)
|
8
9
|
|
9
10
|
bot.command :server do |event, *args|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
if embed
|
16
|
-
event.channel.send_embed(message, embed)
|
11
|
+
if args.empty?
|
12
|
+
event.channel.send_message(
|
13
|
+
"Provide a server address e.g. `!server location.fortressone.org` or use `!servers`"
|
14
|
+
)
|
17
15
|
else
|
18
|
-
|
16
|
+
endpoint = args.first
|
17
|
+
qstat_request = QstatRequest.new(endpoint)
|
18
|
+
message = qstat_request.server_summary
|
19
|
+
embed = qstat_request.to_embed
|
20
|
+
|
21
|
+
if embed
|
22
|
+
event.channel.send_embed(message, embed)
|
23
|
+
else
|
24
|
+
event.channel.send_message(message)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
bot.command :servers do |event|
|
30
|
+
qstat_requests = @endpoints.map do |endpoint|
|
31
|
+
QstatRequest.new(endpoint)
|
32
|
+
end
|
33
|
+
|
34
|
+
message = qstat_requests.map(&:server_summary).join("\n")
|
35
|
+
event.channel.send_message(message)
|
36
|
+
end
|
37
|
+
|
38
|
+
bot.command :active do |event|
|
39
|
+
qstat_requests = @endpoints.map do |endpoint|
|
40
|
+
QstatRequest.new(endpoint)
|
19
41
|
end
|
42
|
+
|
43
|
+
servers_with_players = qstat_requests.select(&:has_players?)
|
44
|
+
|
45
|
+
message = begin
|
46
|
+
if servers_with_players.empty?
|
47
|
+
"All ##{event.channel.name} servers are empty."
|
48
|
+
else
|
49
|
+
servers_with_players.map(&:server_summary).join("\n")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
event.channel.send_message(message)
|
20
54
|
end
|
21
55
|
|
22
56
|
bot.run
|
@@ -4,15 +4,18 @@ class QwtfDiscordBotWatcher < QwtfDiscordBot
|
|
4
4
|
|
5
5
|
def run
|
6
6
|
every(THIRTY_SECONDS) do
|
7
|
-
|
7
|
+
@endpoints.each do |endpoint|
|
8
|
+
request = QstatRequest.new(endpoint)
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
unless request.is_empty?
|
11
|
+
request.player_names.each do |name|
|
12
|
+
unless seen_recently?(endpoint: endpoint, name: name)
|
13
|
+
report_joined(name: name, server_summary: request.server_summary)
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
+
history[endpoint] ||= {}
|
17
|
+
history[endpoint][name] = Time.now
|
18
|
+
end
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -27,8 +30,8 @@ class QwtfDiscordBotWatcher < QwtfDiscordBot
|
|
27
30
|
end
|
28
31
|
end
|
29
32
|
|
30
|
-
def seen_recently?(name)
|
31
|
-
last_seen = history[name]
|
33
|
+
def seen_recently?(endpoint:, name:)
|
34
|
+
last_seen = history[endpoint] && history[endpoint][name]
|
32
35
|
last_seen && (Time.now - last_seen < TEN_MINUTES)
|
33
36
|
end
|
34
37
|
|
data/qwtf_discord_bot.gemspec
CHANGED
@@ -11,8 +11,8 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.description = 'A Discord bot for reporting on QuakeWorld Team ' \
|
12
12
|
'Fortress game servers'
|
13
13
|
|
14
|
-
spec.summary = 'Works by wrapping the excellent CLI server query tool' \
|
15
|
-
'qstat. Accepts
|
14
|
+
spec.summary = 'Works by wrapping the excellent CLI server query tool ' \
|
15
|
+
'qstat. Accepts !server, !servers and !active commands ' \
|
16
16
|
'also periodically checks for new players on the ' \
|
17
17
|
'server and reports about them.'
|
18
18
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qwtf_discord_bot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sheldon Johnson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: discordrb
|
@@ -120,7 +120,7 @@ rubyforge_project:
|
|
120
120
|
rubygems_version: 2.7.6
|
121
121
|
signing_key:
|
122
122
|
specification_version: 4
|
123
|
-
summary: Works by wrapping the excellent CLI server query
|
124
|
-
|
125
|
-
reports about them.
|
123
|
+
summary: Works by wrapping the excellent CLI server query tool qstat. Accepts !server,
|
124
|
+
!servers and !active commands also periodically checks for new players on the server
|
125
|
+
and reports about them.
|
126
126
|
test_files: []
|