qwtf_discord_bot 5.1.6 → 5.2.6

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.
@@ -23,12 +23,14 @@ class QstatRequest
23
23
 
24
24
  def to_message
25
25
  return server_summary if is_empty?
26
+
26
27
  [server_summary, player_table].join("\n")
27
28
  end
28
29
 
29
30
  def server_summary
30
31
  return "#{@endpoint} isn't responding" unless game_map
31
32
  return "#{name} | #{@endpoint} | #{game_map} | #{numplayers}/#{maxplayers}" unless has_spectators?
33
+
32
34
  "#{name} | #{@endpoint} | #{game_map} | #{numplayers}/#{maxplayers} players | #{numspectators}/#{maxspectators} spectators"
33
35
  end
34
36
 
@@ -46,70 +48,70 @@ class QstatRequest
46
48
 
47
49
  private
48
50
 
49
- def has_spectators?
50
- numspectators && numspectators > 0
51
- end
52
-
53
- def teams
54
- @teams ||= build_roster
55
- end
51
+ def has_spectators?
52
+ numspectators && numspectators > 0
53
+ end
56
54
 
57
- def data
58
- @data ||= JSON.parse(result).first
59
- end
55
+ def teams
56
+ @teams ||= build_roster
57
+ end
60
58
 
61
- def execute
62
- %x[qstat -json -P -qws #{@endpoint}]
63
- end
59
+ def data
60
+ @data ||= JSON.parse(result).first
61
+ end
64
62
 
65
- def player_table
66
- players.sort_by { |player| player.team.number }.map(&:to_row).join("\n")
67
- end
63
+ def execute
64
+ `qstat -json -P -qws #{@endpoint}`
65
+ end
68
66
 
69
- def name
70
- data["name"]
71
- end
67
+ def player_table
68
+ players.sort_by { |player| player.team.number }.map(&:to_row).join("\n")
69
+ end
72
70
 
73
- def address
74
- data["address"]
75
- end
71
+ def name
72
+ data['name']
73
+ end
76
74
 
77
- def game_map
78
- data["map"]
79
- end
75
+ def address
76
+ data['address']
77
+ end
80
78
 
81
- def numplayers
82
- data["numplayers"]
83
- end
79
+ def game_map
80
+ data['map']
81
+ end
84
82
 
85
- def maxplayers
86
- data["maxplayers"]
87
- end
83
+ def numplayers
84
+ data['numplayers']
85
+ end
88
86
 
89
- def numspectators
90
- data["numspectators"]
91
- end
87
+ def maxplayers
88
+ data['maxplayers']
89
+ end
92
90
 
93
- def maxspectators
94
- data["maxspectators"]
95
- end
91
+ def numspectators
92
+ data['numspectators']
93
+ end
96
94
 
97
- def build_roster
98
- return nil if is_empty?
95
+ def maxspectators
96
+ data['maxspectators']
97
+ end
99
98
 
100
- roster = Roster.new
99
+ def build_roster
100
+ return nil if is_empty?
101
101
 
102
- data["players"].map do |player_data|
103
- player = Player.new(player_data)
104
- roster.enroll(player)
105
- end
102
+ roster = Roster.new
106
103
 
107
- roster.teams.sort_by { |team| team.number }
104
+ data['players'].map do |player_data|
105
+ player = Player.new(player_data)
106
+ roster.enroll(player)
108
107
  end
109
108
 
110
- def players
111
- data["players"].map do |player_data|
112
- Player.new(player_data)
113
- end
109
+ roster.teams.sort_by { |team| team.number }
110
+ end
111
+
112
+ def players
113
+ data['players'].map do |player_data|
114
+ Player.new(player_data)
114
115
  end
116
+ end
115
117
  end
@@ -21,6 +21,7 @@ module QwtfDiscordBot # :nodoc:
21
21
  def self.config_file
22
22
  return ENV['QWTF_DISCORD_BOT_CONFIG_FILE'] if ENV['QWTF_DISCORD_BOT_CONFIG_FILE']
23
23
  return "#{Dir.pwd}/config.yaml" if FileTest.exist?("#{Dir.pwd}/config.yaml")
24
+
24
25
  "#{Dir.home}/.config/qwtf_discord_bot/config.yaml"
25
26
  end
26
27
 
@@ -6,20 +6,20 @@ class Config
6
6
  end
7
7
 
8
8
  def token
9
- @token ||= @config["token"]
9
+ @token ||= @config['token']
10
10
  end
11
11
 
12
12
  def client_id
13
- @client_id ||= @config["client_id"]
13
+ @client_id ||= @config['client_id']
14
14
  end
15
15
 
16
16
  def endpoints
17
- @endpoints ||= @config["endpoints"].map do |endpoint|
17
+ @endpoints ||= @config['endpoints'].map do |endpoint|
18
18
  Endpoint.new(endpoint)
19
19
  end
20
20
  end
21
21
 
22
22
  def emojis
23
- @emojis ||= @config["emojis"]
23
+ @emojis ||= @config['emojis']
24
24
  end
25
25
  end
@@ -6,7 +6,7 @@ require 'event_decorator'
6
6
  class QwtfDiscordBotPug # :nodoc:
7
7
  include QwtfDiscordBot
8
8
 
9
- FOUR_HOURS = 4 * 60 * 60
9
+ MSG_SNIPPET_DELIMITER = ' · '
10
10
 
11
11
  def run
12
12
  bot = Discordrb::Commands::CommandBot.new(
@@ -17,158 +17,202 @@ class QwtfDiscordBotPug # :nodoc:
17
17
  )
18
18
 
19
19
  bot.command :join do |event, *args|
20
- set_pug(event) do |e, pug|
21
- if pug.joined_players.include?(e.user_id)
22
- message = "You've already joined"
23
- send_and_log_message(message, e.channel)
24
- else
25
- pug.join(e.user_id)
26
-
27
- message = if pug.joined_player_count == 1
28
- [
29
- "#{e.display_name} creates a PUG",
30
- pug.player_slots,
31
- pug.notify_roles
32
- ].join(' | ')
33
- elsif pug.slots_left.between?(1,3)
34
- [
35
- "#{e.display_name} joins the PUG",
36
- pug.player_slots,
37
- "#{pug.slots_left} more",
38
- pug.notify_roles
39
- ].join(' | ')
40
- else
41
- [
42
- "#{e.display_name} joins the PUG",
43
- pug.player_slots
44
- ].join(' | ')
45
- end
46
-
47
- send_and_log_message(message, e.channel)
48
-
49
- if pug.full?
50
- message = start_pug(
51
- pug.player_slots,
52
- e.mentions_for(pug.joined_players)
53
- )
54
-
55
- send_and_log_message(message, e.channel)
56
- end
57
- end
20
+ setup_pug(event) do |e, pug|
21
+ return send_msg("You've already joined", e.channel) if pug.joined?(e.user_id)
22
+
23
+ join_pug(e, pug)
24
+ start_pug(pug, e) if pug.full?
58
25
  end
59
26
  end
60
27
 
61
28
  bot.command :status do |event, *args|
62
- set_pug(event) do |e, pug|
63
- message = if pug.active?
64
- [
65
- "#{e.display_names_for(pug.joined_players).join(', ')} joined",
66
- pug.player_slots
67
- ].join(' | ')
68
- else
69
- 'No PUG has been started. `!join` to create'
70
- end
71
-
72
- send_and_log_message(message, e.channel)
29
+ setup_pug(event) do |e, pug|
30
+ return send_msg('No PUG has been started. `!join` to create', e.channel) unless pug.active?
31
+
32
+ send_msg(
33
+ [
34
+ "#{pug.player_slots} joined",
35
+ pug_teams_message(pug, e).join("\n")
36
+ ].join("\n"),
37
+ e.channel
38
+ )
73
39
  end
74
40
  end
75
41
 
76
- bot.command :maxplayers do |event, *args|
77
- set_pug(event) do |e, pug|
78
- new_maxplayers = args[0]
42
+ bot.command :teamsize do |event, *args|
43
+ setup_pug(event) do |e, pug|
44
+ return send_msg("Team size is #{pug.teamsize}", e.channel) unless args.any?
79
45
 
80
- message = if new_maxplayers
81
- pug.maxplayers = new_maxplayers
82
- "Max number of players set to #{pug.maxplayers} | #{pug.player_slots} joined"
83
- else
84
- "Current max number of players is #{pug.maxplayers} | #{pug.player_slots} joined"
85
- end
46
+ new_teamsize = args[0].to_i
47
+ return send_msg('Team size should be a number higher than 0', e.channel) unless new_teamsize > 0
86
48
 
87
- send_and_log_message(message, e.channel)
49
+ if new_teamsize
50
+ pug.teamsize = new_teamsize
88
51
 
89
- if pug.full?
90
- message = start_pug(
91
- pug.player_slots,
92
- e.mentions_for(pug.joined_players)
52
+ send_msg(
53
+ [
54
+ "Team size set to #{pug.teamsize}",
55
+ "#{pug.player_slots} joined"
56
+ ].join(MSG_SNIPPET_DELIMITER),
57
+ e.channel
93
58
  )
94
59
 
95
- send_and_log_message(message, e.channel)
60
+ start_pug(pug, e) if pug.full?
61
+ else
62
+ send_msg(
63
+ [
64
+ "Current team size is #{pug.teamsize}",
65
+ "#{pug.player_slots} joined"
66
+ ].join(MSG_SNIPPET_DELIMITER),
67
+ e.channel
68
+ )
96
69
  end
97
70
  end
98
71
  end
99
72
 
100
73
  bot.command :leave do |event, *args|
101
- set_pug(event) do |e, pug|
102
- if !pug.active?
103
- message = "There's no active PUG to leave"
104
- send_and_log_message(message, e.channel)
105
- elsif !pug.joined_players.include?(e.user_id)
106
- message = "You're not in the PUG"
107
- send_and_log_message(message, e.channel)
108
- else
109
- pug.leave(e.user_id)
110
- message = "#{e.display_name} leaves the PUG | #{pug.player_slots} remain"
111
- send_and_log_message(message, e.channel)
74
+ setup_pug(event) do |e, pug|
75
+ return send_msg(no_active_pug_message, e.channel) unless pug.active?
76
+ return send_msg("You're not in the PUG", e.channel) unless pug.joined?(e.user_id)
112
77
 
113
- if pug.empty?
114
- message = end_pug(pug)
115
- send_and_log_message(message, e.channel)
116
- end
117
- end
78
+ pug.leave(e.user_id)
79
+
80
+ snippets = [
81
+ "#{e.display_name} leaves the PUG",
82
+ "#{pug.player_slots} remain"
83
+ ]
84
+
85
+ snippets << "#{pug.slots_left} more #{pug.notify_roles}" if pug.slots_left == 1
86
+
87
+ send_msg(
88
+ snippets.join(MSG_SNIPPET_DELIMITER),
89
+ e.channel
90
+ )
91
+
92
+ send_msg(end_pug_message, e.channel) unless pug.active?
118
93
  end
119
94
  end
120
95
 
121
96
  bot.command :kick do |event, *args|
122
- set_pug(event) do |e, pug|
123
- if !pug.active?
124
- message = "There's no active PUG"
125
- return send_and_log_message(message, e.channel)
126
- end
97
+ setup_pug(event) do |e, pug|
98
+ return send_msg(no_active_pug_message, e.channel) unless pug.active?
127
99
 
128
- mention = args[0]
129
- user_id = mention[3..-2].to_i
130
- display_name = e.display_name_for(user_id)
100
+ args.each do |arg|
101
+ unless arg.match(/<@!\d+>/)
102
+ send_msg("#{arg} isn't a valid mention", e.channel)
103
+ next
104
+ end
131
105
 
132
- if !pug.joined_players.include?(user_id)
133
- message = "#{display_name} isn't in the PUG"
134
- send_and_log_message(message, e.channel)
135
- else
136
- pug.leave(user_id)
137
- message = "#{display_name} is kicked from the PUG | #{pug.player_slots} remain"
138
- send_and_log_message(message, e.channel)
106
+ user_id = arg[3..-2].to_i
107
+ display_name = e.display_name_for(user_id) || arg
139
108
 
140
- if pug.empty?
141
- message = end_pug(pug)
142
- send_and_log_message(message, e.channel)
109
+ unless pug.joined?(user_id)
110
+ send_msg("#{display_name} isn't in the PUG", e.channel)
111
+ next
143
112
  end
113
+
114
+ pug.leave(user_id)
115
+
116
+ snippets = [
117
+ "#{display_name} is kicked from the PUG",
118
+ "#{pug.player_slots} remain"
119
+ ]
120
+
121
+ snippets << "#{pug.slots_left} more #{pug.notify_roles}" if pug.slots_left == 1
122
+
123
+ send_msg(
124
+ snippets.join(MSG_SNIPPET_DELIMITER),
125
+ e.channel
126
+ )
127
+
128
+ break send_msg(end_pug_message, e.channel) unless pug.active?
144
129
  end
145
130
  end
146
131
  end
147
132
 
133
+ bot.command :team do |event, *args|
134
+ setup_pug(event) do |e, pug|
135
+ team_no = args[0].to_i
136
+ return send_msg("Choose a team between 1 and 4", e.channel) unless team_no.between?(1, 4)
137
+
138
+ user_id = e.user_id
139
+ return send_msg("You're already in team #{team_no}", e.channel) if pug.team(team_no).include?(user_id)
140
+
141
+ join_pug(e, pug) unless pug.joined?(user_id)
142
+ pug.join_team(team_no: team_no, player_id: user_id)
143
+
144
+ send_msg(
145
+ [
146
+ "#{e.display_name} joins team #{team_no}",
147
+ "#{pug.team_player_count(team_no)}/#{pug.teamsize}"
148
+ ].join(MSG_SNIPPET_DELIMITER), e.channel
149
+ )
150
+
151
+ start_pug(pug, e) if pug.full?
152
+ end
153
+ end
154
+
155
+ bot.command :unteam do |event, *args|
156
+ setup_pug(event) do |e, pug|
157
+ user_id = e.user_id
158
+ return send_msg('No PUG has been started. `!join` to create', e.channel) unless pug.active?
159
+ return send_msg("You aren't in this PUG", e.channel) unless pug.joined?(user_id)
160
+ return send_msg("You aren't in a team", e.channel) if pug.team(0).include?(user_id)
161
+
162
+ pug.join_team(team_no: 0, player_id: user_id)
163
+ send_msg("#{e.display_name} has no team", e.channel)
164
+ end
165
+ end
166
+
167
+ bot.command :win do |event, *args|
168
+ setup_pug(event) do |e, pug|
169
+ return send_msg(no_active_pug_message, e.channel) unless pug.active?
170
+
171
+ winning_team_no = args[0]
172
+
173
+ return send_msg("Not a valid team", e.channel) unless pug.team(winning_team_no).any?
174
+
175
+ pug.won_by(winning_team_no)
176
+
177
+ winning_team = pug.team(winning_team_no).map do |player_id|
178
+ e.display_name_for(player_id)
179
+ end
180
+
181
+ non_winning_teams = pug.actual_teams.tap { |team| team.delete(winning_team_no) }
182
+
183
+ losing_players = non_winning_teams.values.flatten.map do |player_id|
184
+ e.display_name_for(player_id)
185
+ end
186
+
187
+ send_msg(
188
+ "#{winning_team.join(', ')} defeat #{losing_players.join(', ')}",
189
+ e.channel
190
+ )
191
+ end
192
+ end
193
+
148
194
  bot.command :end do |event, *args|
149
- set_pug(event) do |e, pug|
150
- message = if !pug.active?
151
- "There's no active PUG to end"
152
- else
153
- end_pug(pug)
154
- end
155
-
156
- send_and_log_message(message, e.channel)
195
+ setup_pug(event) do |e, pug|
196
+ return send_msg(no_active_pug_message, e.channel) unless pug.active?
197
+
198
+ pug.end_pug
199
+
200
+ send_msg(end_pug_message, e.channel)
157
201
  end
158
202
  end
159
203
 
160
204
  bot.command :notify do |event, *args|
161
- set_pug(event) do |e, pug|
205
+ setup_pug(event) do |e, pug|
162
206
  roles = args.join(' ')
163
207
  pug.notify_roles = roles
164
208
 
165
- message = if roles.empty?
166
- 'Notification removed'
167
- else
168
- "Notification role set to #{roles}"
169
- end
209
+ msg = if roles.empty?
210
+ 'Notification removed'
211
+ else
212
+ "Notification role set to #{roles}"
213
+ end
170
214
 
171
- send_and_log_message(message, e.channel)
215
+ send_msg(msg, e.channel)
172
216
  end
173
217
  end
174
218
 
@@ -177,26 +221,81 @@ class QwtfDiscordBotPug # :nodoc:
177
221
 
178
222
  private
179
223
 
180
- def set_pug(event)
224
+ def join_pug(e, pug)
225
+ pug.join(e.user_id)
226
+
227
+ if pug.joined_player_count == 1
228
+ snippets = ["#{e.display_name} creates a PUG", pug.player_slots, pug.notify_roles]
229
+ else
230
+ snippets = ["#{e.display_name} joins the PUG", pug.player_slots]
231
+ snippets << "#{pug.slots_left} more #{pug.notify_roles}" if pug.slots_left.between?(1, 3)
232
+ end
233
+
234
+ send_msg(snippets.join(MSG_SNIPPET_DELIMITER), e.channel)
235
+ end
236
+
237
+ def setup_pug(event)
181
238
  e = EventDecorator.new(event)
182
239
  pug = Pug.for(e.channel_id)
183
240
  yield(e, pug)
241
+ nil # stop discordrb printing return value
184
242
  end
185
243
 
186
- def start_pug(player_slots, mentions)
187
- [
244
+ def start_pug(pug, event)
245
+ pug_teams = pug.teams.map do |team_no, player_ids|
246
+ team_mentions = player_ids.map do |player_id|
247
+ event.mention_for(player_id)
248
+ end
249
+
250
+ team_status_line(
251
+ team_no: team_no.to_i,
252
+ names: team_mentions,
253
+ teamsize: pug.teamsize
254
+ )
255
+ end
256
+
257
+ msg = [
188
258
  'Time to play!',
189
- player_slots,
190
- mentions.join(' ')
191
- ].join(' | ')
259
+ pug_teams
260
+ ].join("\n")
261
+
262
+ send_msg(msg, event.channel)
192
263
  end
193
264
 
194
- def end_pug(pug)
195
- pug.end_pug
265
+ def pug_teams_message(pug, event)
266
+ pug.teams.map do |team_no, player_ids|
267
+ team_display_names = player_ids.map do |player_id|
268
+ event.display_name_for(player_id)
269
+ end
270
+
271
+ team_status_line(
272
+ team_no: team_no.to_i,
273
+ names: team_display_names,
274
+ teamsize: pug.teamsize
275
+ )
276
+ end
277
+ end
278
+
279
+ def team_status_line(team_no:, names:, teamsize:)
280
+ if team_no.to_i.zero?
281
+ ["No team: #{names.join(', ')}"]
282
+ else
283
+ [
284
+ "Team #{team_no}: #{names.join(', ')}",
285
+ "#{names.count}/#{teamsize}"
286
+ ].join(MSG_SNIPPET_DELIMITER)
287
+ end
288
+ end
289
+
290
+ def end_pug_message
196
291
  'PUG ended'
197
292
  end
198
293
 
199
- def send_and_log_message(message, channel)
294
+ def no_active_pug_message
295
+ "There's no active PUG"
296
+ end
297
+
298
+ def send_msg(message, channel)
200
299
  channel.send_message(message) && puts(message)
201
300
  end
202
301
  end