qwtf_discord_bot 4.2.4 → 5.0.3

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: 661856af97a44fb0c64acbc7c1bc0f031fe5281c5ed820d5d90e1c0b2e00c4ac
4
- data.tar.gz: 774aaabd9a66a7a1c230eacd42d9aa6269e373c6f6cc065d42c30cb71ee216b5
3
+ metadata.gz: 26674622ee7b594155c7eca72c255ea0a26bb9322df7fcf33ff9803beec6460f
4
+ data.tar.gz: 5a8102f704ba9001bf3368ff111a444b6cda358da906d27fa0763daad2d51f41
5
5
  SHA512:
6
- metadata.gz: aed7958152064cb290c25a5afbcfb287a679a7751a572719b7862e766957cdc21e67274efc551d98cf690a6563a8244c3945855e243660b4427b74d9c96610ff
7
- data.tar.gz: 545506b13c8b35825e5bc9a882fdb178a7d4ed3ff4856d03059dab292efe4a512143c328226e6629c91e8303094f95d95ee86208b7aceb36901a772c2660dfac
6
+ metadata.gz: 63f7624a651eb50394af891bb1de1c535d6e33e75b9328d97b8bb88e7a256dc8681102a16d3b231e05b004af5c24e957652c9df32c9e2db295da5c2ee2e65c23
7
+ data.tar.gz: ac02fc2b5f9d631d20f5832250cd49e0cbb1b7a9af0d514feaff7a770dc86b4271abf3d58bfc885043887f3d7d9437dbbd29d32cc4904186c0319eb822edb8ee
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- qwtf_discord_bot (4.1.0)
4
+ qwtf_discord_bot (4.2.6)
5
5
  discordrb (~> 3.3)
6
- redis
6
+ redis (~> 4.1)
7
7
  thor (~> 0.20)
8
8
 
9
9
  GEM
@@ -90,8 +90,9 @@ DEPENDENCIES
90
90
  factory_bot
91
91
  pry
92
92
  qwtf_discord_bot!
93
+ redis
93
94
  rspec
94
95
  thor
95
96
 
96
97
  BUNDLED WITH
97
- 1.17.1
98
+ 1.17.2
data/README.md CHANGED
@@ -66,7 +66,7 @@ A Discord bot for checking the status of QuakeWorld Team Fortress servers
66
66
 
67
67
  ### Commands
68
68
 
69
- There are two modules:
69
+ There are three modules:
70
70
 
71
71
 
72
72
  #### Server
@@ -81,6 +81,19 @@ This responds to discord messages:
81
81
  ![screenshot of bot responding to !server command](server_screenshot.png)
82
82
 
83
83
 
84
+ #### Pug
85
+
86
+ qwtf-discord-bot pug
87
+
88
+ This responds to discord messages:
89
+ - `!join`
90
+ - `!leave`
91
+ - `!status`
92
+ - `!maxplayers <no_of_players>`
93
+ - `!leave`
94
+ - `!role`
95
+
96
+
84
97
  #### Watcher
85
98
 
86
99
  qwtf-discord-bot watcher
@@ -92,18 +105,25 @@ they haven't been connected for more than ten minutes.
92
105
  ![screenshot of bot reporting player joining server](watcher_screenshot.png)
93
106
 
94
107
 
95
- ## Docker
108
+ ## Gem
96
109
 
97
110
  Build:
98
111
 
99
- docker build --tag=discord-bot .
112
+ gem build qwtf_discrd_bot.gemspec
113
+
114
+
115
+ Install:
116
+
117
+
118
+ gem install --local qwtf_discord_bot-$(cat VERSION).gem
100
119
 
101
120
 
102
121
  Push:
103
122
 
104
- docker tag discord-bot fortressone/discord-bot:latest
105
- docker push fortressone/discord-bot:latest
123
+ gem push qwtf_discord_bot-$(cat VERSION).gem
124
+
106
125
 
126
+ ## Docker
107
127
 
108
128
  Run:
109
129
 
@@ -128,6 +148,38 @@ Only discord-bot watcher:
128
148
  discord-bot watcher
129
149
 
130
150
 
151
+ Only discord-bot pug:
152
+
153
+ docker run -it \
154
+ --env QWTF_DISCORD_BOT_CONFIG_FILE=config.yaml \
155
+ --mount type=bind,source="$(pwd)"/config.yaml,target=/discord-bot/config.yaml \
156
+ discord-bot pug
157
+
158
+
159
+ Build:
160
+
161
+ docker build --tag=discord-bot .
162
+
163
+
164
+ Push:
165
+
166
+ docker tag discord-bot fortressone/discord-bot:latest
167
+ docker push fortressone/discord-bot:latest
168
+
169
+
170
+ Create AWS instance:
171
+
172
+ ```
173
+ docker-machine create \
174
+ --driver amazonec2 \
175
+ --amazonec2-access-key <AWS_ACCESS_KEY> \
176
+ --amazonec2-secret-key <AWS_SECRET_KEY> \
177
+ --amazonec2-root-size 30 \
178
+ --amazonec2-region ap-southeast-2 \
179
+ discord-bot
180
+ ```
181
+
182
+
131
183
  ## License
132
184
 
133
185
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.2.4
1
+ 5.0.3
@@ -12,7 +12,7 @@ services:
12
12
  - redis
13
13
  volumes:
14
14
  - type: bind
15
- source: ./config.yaml
15
+ source: "/home/ubuntu/.config/qwtf_discord_bot/config.yaml"
16
16
  target: /discord-bot/config.yaml
17
17
  discord-watcher-bot:
18
18
  image: fortressone/discord-bot:latest
@@ -24,5 +24,17 @@ services:
24
24
  - REDIS_URL=redis://redis
25
25
  volumes:
26
26
  - type: bind
27
- source: ./config.yaml
27
+ source: "/home/ubuntu/.config/qwtf_discord_bot/config.yaml"
28
+ target: /discord-bot/config.yaml
29
+ discord-pug-bot:
30
+ image: fortressone/discord-bot:latest
31
+ command: pug
32
+ restart: always
33
+ depends_on:
34
+ - redis
35
+ environment:
36
+ - REDIS_URL=redis://redis
37
+ volumes:
38
+ - type: bind
39
+ source: "/home/ubuntu/.config/qwtf_discord_bot/config.yaml"
28
40
  target: /discord-bot/config.yaml
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'qwtf_discord_bot'
4
4
  require 'thor'
5
+ require 'pry'
5
6
 
6
7
  class QwtfDiscordBotExe < Thor
7
8
  def self.exit_on_failure?
@@ -14,6 +15,12 @@ class QwtfDiscordBotExe < Thor
14
15
  server_bot.run
15
16
  end
16
17
 
18
+ desc 'pug', 'Start, join, leave, record pick-up games.'
19
+ def pug
20
+ pug_bot = QwtfDiscordBotPug.new
21
+ pug_bot.run
22
+ end
23
+
17
24
  desc 'watcher', 'Watches servers and accounces when a player joins'
18
25
  def watcher
19
26
  watcher_bot = QwtfDiscordBotWatcher.new
@@ -0,0 +1,62 @@
1
+ class EventWrapper
2
+ include QwtfDiscordBot
3
+
4
+ DEFAULT_MAXPLAYERS = 8
5
+
6
+ def initialize(event)
7
+ @event = event
8
+ end
9
+
10
+ def user_id
11
+ @event.user.id
12
+ end
13
+
14
+ def username
15
+ @event.user.username
16
+ end
17
+
18
+ def maxplayers_key
19
+ [pug_key, "maxplayers"].join(":")
20
+ end
21
+
22
+ def maxplayers
23
+ redis.setnx(maxplayers_key, DEFAULT_MAXPLAYERS)
24
+ redis.get(maxplayers_key).to_i
25
+ end
26
+
27
+ def joined_player_count
28
+ redis.scard(players_key).to_i
29
+ end
30
+
31
+ def slots_left
32
+ maxplayers - joined_player_count
33
+ end
34
+
35
+ def pug_key
36
+ ["pug", "channel", @event.channel.id].join(":")
37
+ end
38
+
39
+ def players_key
40
+ [pug_key, "players"].join(":")
41
+ end
42
+
43
+ def player_slots
44
+ "#{joined_player_count}/#{maxplayers}"
45
+ end
46
+
47
+ def users
48
+ @event.server.users
49
+ end
50
+
51
+ def role_key
52
+ [pug_key, "role"].join(":")
53
+ end
54
+
55
+ def role
56
+ redis.get(role_key) || "@here"
57
+ end
58
+
59
+ def pug_active?
60
+ redis.get(pug_key)
61
+ end
62
+ end
@@ -1,9 +1,11 @@
1
1
  require 'qwtf_discord_bot/version'
2
2
  require 'qwtf_discord_bot/qwtf_discord_bot_server'
3
+ require 'qwtf_discord_bot/qwtf_discord_bot_pug'
3
4
  require 'qwtf_discord_bot/qwtf_discord_bot_watcher'
4
5
  require 'qwtf_discord_bot/config'
5
6
  require 'discordrb'
6
7
  require 'yaml'
8
+ require 'redis'
7
9
 
8
10
  require 'qstat_request'
9
11
  require 'player'
@@ -12,9 +14,17 @@ require 'emoji'
12
14
  require 'roster'
13
15
 
14
16
  module QwtfDiscordBot # :nodoc:
15
- CONFIG_FILE = ENV['QWTF_DISCORD_BOT_CONFIG_FILE'] || "#{Dir.pwd}/config.yaml"
16
-
17
17
  def self.config
18
- @config ||= Config.new(CONFIG_FILE)
18
+ @config ||= Config.new(config_file)
19
+ end
20
+
21
+ def self.config_file
22
+ return ENV['QWTF_DISCORD_BOT_CONFIG_FILE'] if ENV['QWTF_DISCORD_BOT_CONFIG_FILE']
23
+ return "#{Dir.pwd}/config.yaml" if FileTest.exist?("#{Dir.pwd}/config.yaml")
24
+ "#{Dir.home}/.config/qwtf_discord_bot/config.yaml"
25
+ end
26
+
27
+ def redis
28
+ Redis.current
19
29
  end
20
30
  end
@@ -0,0 +1,143 @@
1
+ require 'event_wrapper'
2
+
3
+ class QwtfDiscordBotPug
4
+ include QwtfDiscordBot
5
+
6
+ FOUR_HOURS = 4 * 60 * 60
7
+
8
+ def run
9
+ bot = Discordrb::Commands::CommandBot.new(
10
+ token: QwtfDiscordBot.config.token,
11
+ client_id: QwtfDiscordBot.config.client_id,
12
+ help_command: false,
13
+ prefix: '!'
14
+ )
15
+
16
+ bot.command :join do |event, *args|
17
+ e = EventWrapper.new(event)
18
+
19
+ redis.setnx(e.pug_key, Time.now)
20
+ redis.sadd(e.players_key, e.user_id)
21
+
22
+ message = if e.joined_player_count == e.maxplayers
23
+ mentions = joined_users(e).map do |user|
24
+ user.mention
25
+ end
26
+ "Time to play! #{mentions.join(" ")}"
27
+ elsif (e.joined_player_count == 1)
28
+ [
29
+ "#{e.username} creates a PUG",
30
+ e.player_slots,
31
+ e.role,
32
+ ].join(" | ")
33
+ elsif e.slots_left <= 3
34
+ [
35
+ "#{e.username} joins the PUG",
36
+ e.player_slots,
37
+ "#{e.slots_left} more",
38
+ e.role,
39
+ ].join(" | ")
40
+ else
41
+ [
42
+ "#{e.username} joins the PUG",
43
+ e.player_slots,
44
+ ].join(" | ")
45
+ end
46
+
47
+ send_and_log_message(message, event)
48
+ end
49
+
50
+ bot.command :status do |event, *args|
51
+ e = EventWrapper.new(event)
52
+ usernames = joined_users(e).map(&:username)
53
+
54
+ message = if e.pug_active?
55
+ [
56
+ "#{usernames.join(", ")} joined",
57
+ e.player_slots
58
+ ].join(" | ")
59
+ else
60
+ "No PUG has been started. `!join` to create"
61
+ end
62
+
63
+ send_and_log_message(message, event)
64
+ end
65
+
66
+ bot.command :maxplayers do |event, *args|
67
+ e = EventWrapper.new(event)
68
+ new_maxplayers = args[0]
69
+
70
+ message = if new_maxplayers
71
+ redis.set(e.maxplayers_key, new_maxplayers)
72
+ "Max number of players set to #{e.maxplayers} | #{e.player_slots}"
73
+ else
74
+ "Current max number of players is #{e.maxplayers} | #{e.player_slots}"
75
+ end
76
+
77
+ send_and_log_message(message, event)
78
+
79
+ if e.joined_player_count >= e.maxplayers
80
+ mentions = joined_users(e).map do |user|
81
+ user.mention
82
+ end
83
+
84
+ message = "Time to play! #{mentions.join(" ")}"
85
+ send_and_log_message(message, event)
86
+ end
87
+ end
88
+
89
+ bot.command :leave do |event, *args|
90
+ e = EventWrapper.new(event)
91
+
92
+ redis.srem(e.players_key, e.user_id)
93
+
94
+ message = "#{e.username} leaves the PUG | #{e.player_slots}"
95
+
96
+ send_and_log_message(message, event)
97
+
98
+ if e.joined_player_count == 0
99
+ redis.del(e.pug_key)
100
+
101
+ message = "PUG ended"
102
+ send_and_log_message(message, event)
103
+ end
104
+ end
105
+
106
+ bot.command :end do |event, *args|
107
+ e = EventWrapper.new(event)
108
+
109
+ redis.del(e.pug_key)
110
+ redis.del(e.players_key)
111
+
112
+ message = "PUG ended"
113
+ send_and_log_message(message, event)
114
+ end
115
+
116
+ bot.command :role do |event, *args|
117
+ e = EventWrapper.new(event)
118
+ role = args[0]
119
+
120
+ redis.set(e.role_key, role)
121
+
122
+ message = "Notification role set to #{role}"
123
+ send_and_log_message(message, event)
124
+ end
125
+
126
+ bot.run
127
+ end
128
+
129
+ private
130
+
131
+ def send_and_log_message(message, event)
132
+ event.channel.send_message(message)
133
+ puts message
134
+ end
135
+
136
+ def joined_users(event)
137
+ redis.smembers(event.players_key).map do |user_id|
138
+ event.users.find do |user|
139
+ user.id.to_s == user_id
140
+ end
141
+ end
142
+ end
143
+ end
@@ -3,15 +3,16 @@ class QwtfDiscordBotServer
3
3
  bot = Discordrb::Commands::CommandBot.new(
4
4
  token: QwtfDiscordBot.config.token,
5
5
  client_id: QwtfDiscordBot.config.client_id,
6
+ help_command: false,
6
7
  prefix: '!'
7
8
  )
8
9
 
9
10
  bot.command :server do |event, *args|
10
11
  if args.empty?
11
- event.channel.send_message(
12
- 'Provide a server address e.g. `!server sydney.fortressone.org` ' \
13
- 'or use `!active` or `!all`'
14
- )
12
+ message = 'Provide a server address e.g. `!server ' \
13
+ 'sydney.fortressone.org` or use `!active` or `!all`'
14
+ event.channel.send_message(message)
15
+ puts message
15
16
  else
16
17
  endpoint = args.first
17
18
  qstat_response = QstatRequest.new(endpoint)
@@ -20,10 +21,13 @@ class QwtfDiscordBotServer
20
21
 
21
22
  if embed
22
23
  event.channel.send_embed(message, embed)
24
+ puts message
23
25
  else
24
26
  event.channel.send_message(message)
27
+ puts message
25
28
  end
26
29
  end
30
+
27
31
  end
28
32
 
29
33
  bot.command :all do |event|
@@ -34,9 +38,9 @@ class QwtfDiscordBotServer
34
38
  end
35
39
 
36
40
  if endpoints_for_this_channel.empty?
37
- event.channel.send_message(
38
- 'There are no servers associated with this channel'
39
- )
41
+ message = 'There are no servers associated with this channel'
42
+ event.channel.send_message(message)
43
+ puts message
40
44
  else
41
45
  endpoints_for_this_channel.each do |endpoint|
42
46
  qstat_request = QstatRequest.new(endpoint.address)
@@ -45,8 +49,10 @@ class QwtfDiscordBotServer
45
49
 
46
50
  if embed
47
51
  event.channel.send_embed(message, embed)
52
+ puts message
48
53
  else
49
54
  event.channel.send_message(message)
55
+ puts message
50
56
  end
51
57
  end
52
58
  end
@@ -62,9 +68,9 @@ class QwtfDiscordBotServer
62
68
  end
63
69
 
64
70
  if endpoints_for_this_channel.empty?
65
- event.channel.send_message(
66
- 'There are no servers associated with this channel'
67
- )
71
+ message = 'There are no servers associated with this channel'
72
+ event.channel.send_message(message)
73
+ puts message
68
74
  else
69
75
  qstat_requests = endpoints_for_this_channel.map do |endpoint|
70
76
  QstatRequest.new(endpoint.address)
@@ -75,7 +81,9 @@ class QwtfDiscordBotServer
75
81
  end
76
82
 
77
83
  if servers_with_players.empty?
78
- event.channel.send_message("All ##{event.channel.name} servers are empty")
84
+ message = "All ##{event.channel.name} servers are empty"
85
+ event.channel.send_message(message)
86
+ puts message
79
87
  else
80
88
  servers_with_players.each do |server|
81
89
  message = server.server_summary
@@ -83,13 +91,14 @@ class QwtfDiscordBotServer
83
91
 
84
92
  if embed
85
93
  event.channel.send_embed(message, embed)
94
+ puts message
86
95
  else
87
96
  event.channel.send_message(message)
97
+ puts message
88
98
  end
89
99
  end
90
100
  end
91
101
  end
92
-
93
102
  return nil
94
103
  end
95
104
 
@@ -1,5 +1,3 @@
1
- require "redis"
2
-
3
1
  class QwtfDiscordBotWatcher
4
2
  include QwtfDiscordBot
5
3
 
@@ -14,7 +12,7 @@ class QwtfDiscordBotWatcher
14
12
  next if request.is_empty?
15
13
 
16
14
  request.player_names.each do |name|
17
- redis_key = "#{address}:#{name}"
15
+ redis_key = ["watcher", address, name].join(":")
18
16
 
19
17
  unless seen_recently?(redis_key)
20
18
  endpoint.channel_ids.each do |channel_id|
@@ -51,16 +49,14 @@ class QwtfDiscordBotWatcher
51
49
  end
52
50
 
53
51
  def report_joined(name:, channel_id:, server_summary:)
52
+ message = "#{name} joins #{server_summary}"
53
+
54
54
  Discordrb::API::Channel.create_message(
55
55
  "Bot #{QwtfDiscordBot.config.token}",
56
56
  channel_id,
57
- "#{name} has joined #{server_summary}"
57
+ message
58
58
  )
59
- end
60
-
61
- private
62
59
 
63
- def redis
64
- @redis ||= Redis.new
60
+ puts message
65
61
  end
66
62
  end
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.2.4
4
+ version: 5.0.3
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-01-19 00:00:00.000000000 Z
11
+ date: 2020-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: discordrb
@@ -104,10 +104,12 @@ files:
104
104
  - exe/qwtf_discord_bot
105
105
  - lib/emoji.rb
106
106
  - lib/endpoint.rb
107
+ - lib/event_wrapper.rb
107
108
  - lib/player.rb
108
109
  - lib/qstat_request.rb
109
110
  - lib/qwtf_discord_bot.rb
110
111
  - lib/qwtf_discord_bot/config.rb
112
+ - lib/qwtf_discord_bot/qwtf_discord_bot_pug.rb
111
113
  - lib/qwtf_discord_bot/qwtf_discord_bot_server.rb
112
114
  - lib/qwtf_discord_bot/qwtf_discord_bot_watcher.rb
113
115
  - lib/qwtf_discord_bot/version.rb
@@ -135,8 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
137
  - !ruby/object:Gem::Version
136
138
  version: '0'
137
139
  requirements: []
138
- rubyforge_project:
139
- rubygems_version: 2.7.6.2
140
+ rubygems_version: 3.1.2
140
141
  signing_key:
141
142
  specification_version: 4
142
143
  summary: Works by wrapping the excellent CLI server query tool qstat. Accepts !server,