qwtf_discord_bot 5.4.9 → 5.5.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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/docker-compose.yml +13 -0
- data/exe/qwtf_discord_bot +6 -0
- data/lib/dashboard.rb +40 -0
- data/lib/qstat_request.rb +48 -2
- data/lib/qwtf_discord_bot.rb +4 -3
- data/lib/qwtf_discord_bot/config.rb +5 -0
- data/lib/qwtf_discord_bot/qwtf_discord_bot_dashboard.rb +41 -0
- data/lib/qwtf_discord_bot/qwtf_discord_bot_pug.rb +80 -41
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 114b6c7c1ecc4b4cd957b359b58f42af35a29979830fbb397121ef37d26b2fdd
|
4
|
+
data.tar.gz: '0098c992179231b57e8b443b8f658354e5e05bc4e284de739c1e442c771d163f'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8da38ea19d0f3bd0ebcc0bf82468d8347ec7d343f0f67acafb1fa0bb567b50ad28ad2af268022cf4f1fd6e1f405203740318a6a9112ce9d4971a90d3fa66f68
|
7
|
+
data.tar.gz: c801b72f1614f818816a6ced4737d58cb4b59dfe2c5db779b22cf7d124ceb364bdc58d47307f842efe58992eee31c6c729e769f8b6a3f795b9ad462eb76b7e1c
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
5.
|
1
|
+
5.5.0
|
data/docker-compose.yml
CHANGED
@@ -39,3 +39,16 @@ services:
|
|
39
39
|
- type: bind
|
40
40
|
source: "/home/ubuntu/.config/qwtf_discord_bot/config.yaml"
|
41
41
|
target: /discord-bot/config.yaml
|
42
|
+
discord-dashboard-bot:
|
43
|
+
image: fortressone/discord-bot:latest
|
44
|
+
command: dashboard
|
45
|
+
restart: always
|
46
|
+
depends_on:
|
47
|
+
- redis
|
48
|
+
environment:
|
49
|
+
- REDIS_URL=redis://redis
|
50
|
+
- RATINGS_API_URL
|
51
|
+
volumes:
|
52
|
+
- type: bind
|
53
|
+
source: "/home/ubuntu/.config/qwtf_discord_bot/config.yaml"
|
54
|
+
target: /discord-bot/config.yaml
|
data/exe/qwtf_discord_bot
CHANGED
@@ -26,6 +26,12 @@ class QwtfDiscordBotExe < Thor
|
|
26
26
|
watcher_bot = QwtfDiscordBotWatcher.new
|
27
27
|
watcher_bot.run
|
28
28
|
end
|
29
|
+
|
30
|
+
desc 'dashboard', 'A live dashboard with active server information'
|
31
|
+
def dashboard
|
32
|
+
dashboard_bot = QwtfDiscordBotDashboard.new
|
33
|
+
dashboard_bot.run
|
34
|
+
end
|
29
35
|
end
|
30
36
|
|
31
37
|
QwtfDiscordBotExe.start
|
data/lib/dashboard.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
class Dashboard
|
2
|
+
def initialize(channel, bot)
|
3
|
+
@channel_id = channel["id"]
|
4
|
+
@endpoints = channel["endpoints"]
|
5
|
+
@bot = bot
|
6
|
+
@messages = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def update
|
10
|
+
@endpoints.each do |endpoint|
|
11
|
+
qstat_request = QstatRequest.new(endpoint)
|
12
|
+
|
13
|
+
if qstat_request.is_empty?
|
14
|
+
next unless @messages[endpoint]
|
15
|
+
|
16
|
+
@messages[endpoint].delete
|
17
|
+
@messages.delete(endpoint)
|
18
|
+
end
|
19
|
+
|
20
|
+
embed = qstat_request.to_full_embed
|
21
|
+
|
22
|
+
@messages[endpoint] = if @messages[endpoint]
|
23
|
+
@messages[endpoint].edit(nil, embed)
|
24
|
+
else
|
25
|
+
channel.send_embed(nil, embed)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def channel
|
33
|
+
data = Discordrb::API::Channel.resolve(
|
34
|
+
"Bot #{QwtfDiscordBot.config.token}",
|
35
|
+
@channel_id
|
36
|
+
)
|
37
|
+
|
38
|
+
Discordrb::Channel.new(JSON.parse(data), @bot)
|
39
|
+
end
|
40
|
+
end
|
data/lib/qstat_request.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
class QstatRequest
|
2
|
+
MSG_SNIPPET_DELIMITER = ' · '
|
3
|
+
|
2
4
|
attr_accessor :result
|
3
5
|
|
4
6
|
def initialize(endpoint)
|
@@ -21,6 +23,19 @@ class QstatRequest
|
|
21
23
|
embed
|
22
24
|
end
|
23
25
|
|
26
|
+
def to_full_embed
|
27
|
+
Discordrb::Webhooks::Embed.new.tap do |embed|
|
28
|
+
embed.add_field(
|
29
|
+
name: name,
|
30
|
+
value: embed_summary,
|
31
|
+
)
|
32
|
+
|
33
|
+
teams.each do |team|
|
34
|
+
embed.add_field(team.to_embed_field)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
24
39
|
def to_message
|
25
40
|
return server_summary if is_empty?
|
26
41
|
|
@@ -29,9 +44,40 @@ class QstatRequest
|
|
29
44
|
|
30
45
|
def server_summary
|
31
46
|
return "#{@endpoint} isn't responding" unless game_map
|
32
|
-
return "#{name} | #{@endpoint} | #{game_map} | #{numplayers}/#{maxplayers}" unless has_spectators?
|
33
47
|
|
34
|
-
|
48
|
+
if !has_spectators?
|
49
|
+
return [
|
50
|
+
name,
|
51
|
+
@endpoint,
|
52
|
+
game_map,
|
53
|
+
"#{numplayers}/#{maxplayers}"
|
54
|
+
].join(MSG_SNIPPET_DELIMITER)
|
55
|
+
end
|
56
|
+
|
57
|
+
[
|
58
|
+
name,
|
59
|
+
@endpoint,
|
60
|
+
game_map,
|
61
|
+
"#{numplayers}/#{maxplayers} players",
|
62
|
+
"#{numspectators}/#{maxspectators} spectators"
|
63
|
+
].join(MSG_SNIPPET_DELIMITER)
|
64
|
+
end
|
65
|
+
|
66
|
+
def embed_summary
|
67
|
+
if !has_spectators?
|
68
|
+
return [
|
69
|
+
@endpoint,
|
70
|
+
game_map,
|
71
|
+
"#{numplayers}/#{maxplayers}"
|
72
|
+
].join(MSG_SNIPPET_DELIMITER)
|
73
|
+
end
|
74
|
+
|
75
|
+
[
|
76
|
+
@endpoint,
|
77
|
+
game_map,
|
78
|
+
"#{numplayers}/#{maxplayers} players",
|
79
|
+
"#{numspectators}/#{maxspectators} spectators"
|
80
|
+
].join(MSG_SNIPPET_DELIMITER)
|
35
81
|
end
|
36
82
|
|
37
83
|
def is_empty?
|
data/lib/qwtf_discord_bot.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
+
require 'discordrb'
|
2
|
+
require 'yaml'
|
3
|
+
require 'redis'
|
1
4
|
require 'qwtf_discord_bot/version'
|
2
5
|
require 'qwtf_discord_bot/qwtf_discord_bot_server'
|
3
6
|
require 'qwtf_discord_bot/qwtf_discord_bot_pug'
|
4
7
|
require 'qwtf_discord_bot/qwtf_discord_bot_watcher'
|
8
|
+
require 'qwtf_discord_bot/qwtf_discord_bot_dashboard'
|
5
9
|
require 'qwtf_discord_bot/config'
|
6
|
-
require 'discordrb'
|
7
|
-
require 'yaml'
|
8
|
-
require 'redis'
|
9
10
|
|
10
11
|
require 'qstat_request'
|
11
12
|
require 'player'
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'endpoint'
|
2
|
+
require 'dashboard'
|
2
3
|
|
3
4
|
class Config
|
4
5
|
def initialize(config)
|
@@ -19,6 +20,10 @@ class Config
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
def dashboards
|
24
|
+
@dashboards ||= @config['dashboards']
|
25
|
+
end
|
26
|
+
|
22
27
|
def emojis
|
23
28
|
@emojis ||= @config['emojis']
|
24
29
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class QwtfDiscordBotDashboard
|
2
|
+
THIRTY_SECONDS = 30
|
3
|
+
|
4
|
+
def run
|
5
|
+
bot = Discordrb::Commands::CommandBot.new(
|
6
|
+
token: QwtfDiscordBot.config.token,
|
7
|
+
client_id: QwtfDiscordBot.config.client_id,
|
8
|
+
help_command: false,
|
9
|
+
prefix: proc do |message|
|
10
|
+
match = /^\!(\w+)(.*)/.match(message.content)
|
11
|
+
if match
|
12
|
+
first = match[1]
|
13
|
+
rest = match[2]
|
14
|
+
# Return the modified string with the first word lowercase:
|
15
|
+
"#{first.downcase}#{rest}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
)
|
19
|
+
|
20
|
+
@dashboards ||= QwtfDiscordBot.config.dashboards.map do |channel|
|
21
|
+
Dashboard.new(channel, bot)
|
22
|
+
end
|
23
|
+
|
24
|
+
every(THIRTY_SECONDS) do
|
25
|
+
@dashboards.each do |dashboard|
|
26
|
+
dashboard.update
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def every(n_seconds)
|
34
|
+
loop do
|
35
|
+
before = Time.now
|
36
|
+
yield
|
37
|
+
interval = n_seconds - (Time.now - before)
|
38
|
+
sleep(interval) if interval > 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -65,9 +65,9 @@ class QwtfDiscordBotPug # :nodoc:
|
|
65
65
|
0
|
66
66
|
end
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
|
69
|
+
message_obj = choose_fair_teams(pug: pug, event: e, iteration: iteration)
|
70
|
+
status(pug: pug, event: e, message_obj: message_obj) if message_obj
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -261,15 +261,6 @@ class QwtfDiscordBotPug # :nodoc:
|
|
261
261
|
|
262
262
|
user_id = mention_to_user_id(mention)
|
263
263
|
display_name = e.display_name_for(user_id) || arg
|
264
|
-
|
265
|
-
unless pug.joined?(user_id)
|
266
|
-
send_embedded_message(
|
267
|
-
description: "#{display_name} isn't in the PUG",
|
268
|
-
channel: e.channel
|
269
|
-
)
|
270
|
-
next
|
271
|
-
end
|
272
|
-
|
273
264
|
pug.join_team(team_no: team_no, player_id: user_id)
|
274
265
|
|
275
266
|
send_embedded_message(
|
@@ -297,26 +288,47 @@ class QwtfDiscordBotPug # :nodoc:
|
|
297
288
|
)
|
298
289
|
end
|
299
290
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
291
|
+
if args.empty?
|
292
|
+
unless pug.joined?(user_id)
|
293
|
+
return send_embedded_message(
|
294
|
+
description: "You aren't in this PUG",
|
295
|
+
channel: e.channel
|
296
|
+
)
|
297
|
+
end
|
306
298
|
|
307
|
-
|
308
|
-
|
309
|
-
|
299
|
+
if pug.team(0).include?(user_id)
|
300
|
+
return send_embedded_message(
|
301
|
+
description: "You aren't in a team",
|
302
|
+
channel: e.channel
|
303
|
+
)
|
304
|
+
end
|
305
|
+
|
306
|
+
pug.join_team(team_no: 0, player_id: user_id)
|
307
|
+
|
308
|
+
send_embedded_message(
|
309
|
+
description: "#{e.display_name} leaves team",
|
310
310
|
channel: e.channel
|
311
311
|
)
|
312
|
-
|
312
|
+
else
|
313
|
+
args.each do |mention|
|
314
|
+
unless mention.match(/<@!\d+>/)
|
315
|
+
send_embedded_message(
|
316
|
+
description: "#{arg} isn't a valid mention",
|
317
|
+
channel: e.channel
|
318
|
+
)
|
319
|
+
next
|
320
|
+
end
|
313
321
|
|
314
|
-
|
322
|
+
user_id = mention_to_user_id(mention)
|
323
|
+
display_name = e.display_name_for(user_id) || arg
|
324
|
+
pug.join_team(team_no: 0, player_id: user_id)
|
315
325
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
326
|
+
send_embedded_message(
|
327
|
+
description: "#{display_name} leaves team",
|
328
|
+
channel: e.channel
|
329
|
+
)
|
330
|
+
end
|
331
|
+
end
|
320
332
|
end
|
321
333
|
end
|
322
334
|
|
@@ -329,6 +341,13 @@ class QwtfDiscordBotPug # :nodoc:
|
|
329
341
|
)
|
330
342
|
end
|
331
343
|
|
344
|
+
if !pug.full?
|
345
|
+
return send_embedded_message(
|
346
|
+
description: "Can't report unless PUG is full",
|
347
|
+
channel: event.channel
|
348
|
+
)
|
349
|
+
end
|
350
|
+
|
332
351
|
unless args.any?
|
333
352
|
return send_embedded_message(
|
334
353
|
description: "Specify winning team; e.g. `!win 1`",
|
@@ -361,7 +380,7 @@ class QwtfDiscordBotPug # :nodoc:
|
|
361
380
|
teams.merge({ name => { players: players, result: result } })
|
362
381
|
end
|
363
382
|
|
364
|
-
post_results(
|
383
|
+
id = post_results(
|
365
384
|
{
|
366
385
|
match: {
|
367
386
|
map: pug.game_map,
|
@@ -372,10 +391,10 @@ class QwtfDiscordBotPug # :nodoc:
|
|
372
391
|
}
|
373
392
|
}
|
374
393
|
}.to_json
|
375
|
-
)
|
394
|
+
).body
|
376
395
|
|
377
396
|
send_embedded_message(
|
378
|
-
description: "#{TEAM_NAMES[winning_team_no]} wins. [Ratings](http://ratings.fortressone.org)",
|
397
|
+
description: "#{TEAM_NAMES[winning_team_no]} wins game ##{id}. [Ratings](http://ratings.fortressone.org)",
|
379
398
|
channel: e.channel
|
380
399
|
)
|
381
400
|
end
|
@@ -390,6 +409,13 @@ class QwtfDiscordBotPug # :nodoc:
|
|
390
409
|
)
|
391
410
|
end
|
392
411
|
|
412
|
+
if !pug.full?
|
413
|
+
return send_embedded_message(
|
414
|
+
description: "Can't report unless PUG is full",
|
415
|
+
channel: event.channel
|
416
|
+
)
|
417
|
+
end
|
418
|
+
|
393
419
|
if pug.actual_teams.count < 2
|
394
420
|
return send_embedded_message(
|
395
421
|
description: "There must be at least two teams with players to submit a result",
|
@@ -405,7 +431,7 @@ class QwtfDiscordBotPug # :nodoc:
|
|
405
431
|
teams.merge({ name => { players: players, result: 0 } })
|
406
432
|
end
|
407
433
|
|
408
|
-
post_results(
|
434
|
+
id = post_results(
|
409
435
|
{
|
410
436
|
match: {
|
411
437
|
map: pug.game_map,
|
@@ -416,10 +442,10 @@ class QwtfDiscordBotPug # :nodoc:
|
|
416
442
|
}
|
417
443
|
}
|
418
444
|
}.to_json
|
419
|
-
)
|
445
|
+
).body
|
420
446
|
|
421
447
|
send_embedded_message(
|
422
|
-
description: "Match drawn. [Ratings](http://ratings.fortressone.org)",
|
448
|
+
description: "Match ##{id} drawn. [Ratings](http://ratings.fortressone.org)",
|
423
449
|
channel: e.channel
|
424
450
|
)
|
425
451
|
end
|
@@ -610,7 +636,7 @@ class QwtfDiscordBotPug # :nodoc:
|
|
610
636
|
) && nil
|
611
637
|
end
|
612
638
|
|
613
|
-
send_embedded_message(
|
639
|
+
message_obj = send_embedded_message(
|
614
640
|
description: "Choosing fair teams...",
|
615
641
|
channel: event.channel
|
616
642
|
)
|
@@ -621,7 +647,8 @@ class QwtfDiscordBotPug # :nodoc:
|
|
621
647
|
if !teams
|
622
648
|
return send_embedded_message(
|
623
649
|
description: "There are only #{combinations.count} possible combinations",
|
624
|
-
channel: event.channel
|
650
|
+
channel: event.channel,
|
651
|
+
message_obj: message_obj
|
625
652
|
) && nil
|
626
653
|
end
|
627
654
|
|
@@ -630,17 +657,20 @@ class QwtfDiscordBotPug # :nodoc:
|
|
630
657
|
pug.join_team(team_no: team_no, player_id: player_id)
|
631
658
|
end
|
632
659
|
end
|
660
|
+
|
661
|
+
message_obj
|
633
662
|
end
|
634
663
|
|
635
|
-
def status(pug:, event:)
|
664
|
+
def status(pug:, event:, message_obj: nil)
|
636
665
|
footer = [
|
637
|
-
pug.game_map,
|
638
|
-
"#{pug.player_slots} joined"
|
666
|
+
pug.game_map || "No map selected",
|
667
|
+
"#{pug.player_slots} joined",
|
639
668
|
].compact.join(MSG_SNIPPET_DELIMITER)
|
640
669
|
|
641
670
|
send_embedded_message(
|
642
671
|
description: nil,
|
643
|
-
channel: event.channel
|
672
|
+
channel: event.channel,
|
673
|
+
message_obj: message_obj
|
644
674
|
) do |embed|
|
645
675
|
embed.footer = Discordrb::Webhooks::EmbedFooter.new(
|
646
676
|
text: footer
|
@@ -717,11 +747,20 @@ class QwtfDiscordBotPug # :nodoc:
|
|
717
747
|
"There's no active PUG"
|
718
748
|
end
|
719
749
|
|
720
|
-
def send_embedded_message(message: nil, description: nil, channel:)
|
750
|
+
def send_embedded_message(message: nil, description: nil, channel:, message_obj: nil)
|
721
751
|
embed = Discordrb::Webhooks::Embed.new
|
722
752
|
embed.description = description
|
723
753
|
yield(embed) if block_given?
|
724
|
-
|
754
|
+
|
755
|
+
if message_obj
|
756
|
+
message_obj.edit(message, embed).tap do
|
757
|
+
puts(message)
|
758
|
+
end
|
759
|
+
else
|
760
|
+
channel.send_embed(message, embed).tap do
|
761
|
+
puts(message)
|
762
|
+
end
|
763
|
+
end
|
725
764
|
end
|
726
765
|
|
727
766
|
def post_results(json)
|
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: 5.
|
4
|
+
version: 5.5.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: 2020-
|
11
|
+
date: 2020-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: discordrb
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- emoji/red_soldier.png
|
103
103
|
- emoji/red_spy.png
|
104
104
|
- exe/qwtf_discord_bot
|
105
|
+
- lib/dashboard.rb
|
105
106
|
- lib/emoji.rb
|
106
107
|
- lib/endpoint.rb
|
107
108
|
- lib/event_decorator.rb
|
@@ -110,6 +111,7 @@ files:
|
|
110
111
|
- lib/qstat_request.rb
|
111
112
|
- lib/qwtf_discord_bot.rb
|
112
113
|
- lib/qwtf_discord_bot/config.rb
|
114
|
+
- lib/qwtf_discord_bot/qwtf_discord_bot_dashboard.rb
|
113
115
|
- lib/qwtf_discord_bot/qwtf_discord_bot_pug.rb
|
114
116
|
- lib/qwtf_discord_bot/qwtf_discord_bot_server.rb
|
115
117
|
- lib/qwtf_discord_bot/qwtf_discord_bot_watcher.rb
|