qwtf_discord_bot 5.4.10 → 5.5.1

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: c5bfd247ff3e811ab845a1cef86f043b93f54a6f30769885547d0ba1601c15ef
4
- data.tar.gz: 72aebecdfaa233cd62e4d36b25c474a319dae5a1fa12d8ea8711536f23cf9549
3
+ metadata.gz: b1d76ac11d350eb38fbb60579e3ce26d561066f17e1bcda29029791afd98d36f
4
+ data.tar.gz: 1e75a7c3cecf17134bd41e2a9370bce29f82260319cd4d78bd9e9638e1c8e3af
5
5
  SHA512:
6
- metadata.gz: 89c358f811c6c0d17b31fb26e1a8d6234bf170f82bd5a820da5d8474052a42594f1adeafcd6fa387488147559370533a10d73bf50526bdfedb5b948325f78f7d
7
- data.tar.gz: e2eb01bcd75ff2ab9251452c6cfac97b381d1199d5fddc5a146ee451def5e56747b4528e2977fd15e2d3d732a63cac03a1dcaa38a37cecaa6a75758075bdf770
6
+ metadata.gz: d13de4098fde37b346b4a668befed0c59ba73cae7a7640b69356064d1446c081af3b0552ef651896bd4c08b2548882a1386508992f12022717e9519eb5317dd2
7
+ data.tar.gz: c0868734a288588818370904904a407789857c74164d4b4ef42e27bafc68724238dcd4235bd7c625d79f72949109eef08ead1f03e2dea5a9ab39472132d2e1be
data/VERSION CHANGED
@@ -1 +1 @@
1
- 5.4.10
1
+ 5.5.1
@@ -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,42 @@
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
+ if @messages[endpoint]
15
+ @messages[endpoint].delete
16
+ @messages.delete(endpoint)
17
+ end
18
+
19
+ next
20
+ end
21
+
22
+ embed = qstat_request.to_full_embed
23
+
24
+ @messages[endpoint] = if @messages[endpoint]
25
+ @messages[endpoint].edit(nil, embed)
26
+ else
27
+ channel.send_embed(nil, embed)
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def channel
35
+ data = Discordrb::API::Channel.resolve(
36
+ "Bot #{QwtfDiscordBot.config.token}",
37
+ @channel_id
38
+ )
39
+
40
+ Discordrb::Channel.new(JSON.parse(data), @bot)
41
+ end
42
+ 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?
@@ -97,7 +143,7 @@ class QstatRequest
97
143
  end
98
144
 
99
145
  def build_roster
100
- return nil if is_empty?
146
+ return [] if is_empty?
101
147
 
102
148
  roster = Roster.new
103
149
 
@@ -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
@@ -288,26 +288,47 @@ class QwtfDiscordBotPug # :nodoc:
288
288
  )
289
289
  end
290
290
 
291
- unless pug.joined?(user_id)
292
- return send_embedded_message(
293
- description: "You aren't in this PUG",
294
- channel: e.channel
295
- )
296
- 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
297
298
 
298
- if pug.team(0).include?(user_id)
299
- return send_embedded_message(
300
- 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",
301
310
  channel: e.channel
302
311
  )
303
- 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
304
321
 
305
- 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)
306
325
 
307
- send_embedded_message(
308
- description: "#{e.display_name} leaves team",
309
- channel: e.channel
310
- )
326
+ send_embedded_message(
327
+ description: "#{display_name} leaves team",
328
+ channel: e.channel
329
+ )
330
+ end
331
+ end
311
332
  end
312
333
  end
313
334
 
@@ -320,6 +341,13 @@ class QwtfDiscordBotPug # :nodoc:
320
341
  )
321
342
  end
322
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
+
323
351
  unless args.any?
324
352
  return send_embedded_message(
325
353
  description: "Specify winning team; e.g. `!win 1`",
@@ -352,7 +380,7 @@ class QwtfDiscordBotPug # :nodoc:
352
380
  teams.merge({ name => { players: players, result: result } })
353
381
  end
354
382
 
355
- post_results(
383
+ id = post_results(
356
384
  {
357
385
  match: {
358
386
  map: pug.game_map,
@@ -363,10 +391,10 @@ class QwtfDiscordBotPug # :nodoc:
363
391
  }
364
392
  }
365
393
  }.to_json
366
- )
394
+ ).body
367
395
 
368
396
  send_embedded_message(
369
- 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)",
370
398
  channel: e.channel
371
399
  )
372
400
  end
@@ -381,6 +409,13 @@ class QwtfDiscordBotPug # :nodoc:
381
409
  )
382
410
  end
383
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
+
384
419
  if pug.actual_teams.count < 2
385
420
  return send_embedded_message(
386
421
  description: "There must be at least two teams with players to submit a result",
@@ -396,7 +431,7 @@ class QwtfDiscordBotPug # :nodoc:
396
431
  teams.merge({ name => { players: players, result: 0 } })
397
432
  end
398
433
 
399
- post_results(
434
+ id = post_results(
400
435
  {
401
436
  match: {
402
437
  map: pug.game_map,
@@ -407,10 +442,10 @@ class QwtfDiscordBotPug # :nodoc:
407
442
  }
408
443
  }
409
444
  }.to_json
410
- )
445
+ ).body
411
446
 
412
447
  send_embedded_message(
413
- description: "Match drawn. [Ratings](http://ratings.fortressone.org)",
448
+ description: "Match ##{id} drawn. [Ratings](http://ratings.fortressone.org)",
414
449
  channel: e.channel
415
450
  )
416
451
  end
@@ -628,8 +663,8 @@ class QwtfDiscordBotPug # :nodoc:
628
663
 
629
664
  def status(pug:, event:, message_obj: nil)
630
665
  footer = [
631
- pug.game_map,
632
- "#{pug.player_slots} joined"
666
+ pug.game_map || "No map selected",
667
+ "#{pug.player_slots} joined",
633
668
  ].compact.join(MSG_SNIPPET_DELIMITER)
634
669
 
635
670
  send_embedded_message(
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.10
4
+ version: 5.5.1
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-31 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