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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3978acdc270b907c20e237c57690192b753aa96be251edcda59f80f60fa188a5
4
- data.tar.gz: fbda19b74c0f215cbd2789743db1e303352dae5488fe4633e683c7982b7295f2
3
+ metadata.gz: 114b6c7c1ecc4b4cd957b359b58f42af35a29979830fbb397121ef37d26b2fdd
4
+ data.tar.gz: '0098c992179231b57e8b443b8f658354e5e05bc4e284de739c1e442c771d163f'
5
5
  SHA512:
6
- metadata.gz: 0b343f7bbcf1435df653f9cc6a810db2a09472d2238134a8acc39446c1e54a828a5c6d1e5fbef318271bd0019d70304febe39aab107ceefe8ceada2ae7318a99
7
- data.tar.gz: e627fca364cd5f51fa3514c4c8c66d9bf80486f6114778bf82086165706503d808d89fc2b717ea4e2bcfc70d8fe7de5376432f68436a836d49e92b833611add4
6
+ metadata.gz: c8da38ea19d0f3bd0ebcc0bf82468d8347ec7d343f0f67acafb1fa0bb567b50ad28ad2af268022cf4f1fd6e1f405203740318a6a9112ce9d4971a90d3fa66f68
7
+ data.tar.gz: c801b72f1614f818816a6ced4737d58cb4b59dfe2c5db779b22cf7d124ceb364bdc58d47307f842efe58992eee31c6c729e769f8b6a3f795b9ad462eb76b7e1c
data/VERSION CHANGED
@@ -1 +1 @@
1
- 5.4.9
1
+ 5.5.0
@@ -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
@@ -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
@@ -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
@@ -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
- "#{name} | #{@endpoint} | #{game_map} | #{numplayers}/#{maxplayers} players | #{numspectators}/#{maxspectators} spectators"
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?
@@ -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
- if choose_fair_teams(pug: pug, event: e, iteration: iteration)
69
- status(pug: pug, event: e)
70
- end
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
- unless pug.joined?(user_id)
301
- return send_embedded_message(
302
- description: "You aren't in this PUG",
303
- channel: e.channel
304
- )
305
- end
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
- if pug.team(0).include?(user_id)
308
- return send_embedded_message(
309
- description: "You aren't in a team",
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
- end
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
- pug.join_team(team_no: 0, player_id: user_id)
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
- send_embedded_message(
317
- description: "#{e.display_name} leaves team",
318
- channel: e.channel
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
- channel.send_embed(message, embed) && puts(message)
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.9
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-10-28 00:00:00.000000000 Z
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