Class: ESM::API

Inherits:
Object
  • Object
show all
Defined in:
lib/esm/api.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.runObject



5
6
7
8
# File 'lib/esm/api.rb', line 5

def self.run
  port = ESM.config.ports.api
  @instance = DRb::DRbServer.new("druby://localhost:#{port}", new)
end

.stopObject



10
11
12
# File 'lib/esm/api.rb', line 10

def self.stop
  @instance.stop_service
end

Instance Method Details

#channel(id:, **filters) ⇒ Object

Gets a channel by its ID. The bot must have send access to this channel

Parameters:

  • id (String)

    The discord channel ID

  • community_id (String)

    Restricts the search to this community's guild

  • user_id (String)

    Requires the channel to be readable by this user's discord member



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/esm/api.rb', line 92

def channel(id:, **filters)
  info!(event: "channel", id:, filters:)

  channel = ESM.bot.channel(id)
  return if channel.nil?
  return unless ESM.bot.channel_permission?(:send_messages, channel)

  if (community_id = filters[:community_id])
    community = ESM::Community.find_by(id: community_id)
    return if community.nil?
    return unless channel.server.id.to_s == community.guild_id
  end

  if (user_id = filters[:user_id])
    user = ESM::User.find_by(id: user_id)
    return if user.nil?
    return unless user.channel_permission?(:read_messages, channel)
  end

  channel.to_h
end

#channel_send(id:, message:) ⇒ Object

Sends a message to a channel id => ID of the channel to send message => The message to send encoded as JSON



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/esm/api.rb', line 117

def channel_send(id:, message:)
  info!(event: "channel:send", id: id, message: message)

  channel = ESM.bot.channel(id) || ESM.bot.user(id)
  channel = channel.pm if channel.is_a?(Discordrb::User)
  return if channel.nil?
  return if channel.text? && !ESM.bot.channel_permission?(:send_messages, channel)

  message = message.to_h || message
  message = ESM::Embed.from_hash(message) if message.is_a?(Hash)

  ESM.bot.deliver(message, to: channel)
end

#community_channels(id:, user_id:) ⇒ Object

Gets all channels for a community

Parameters:

  • id (String)

    The database ID for the community

  • user_id (String)

    The database ID for a user to check if they have read permissions



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/esm/api.rb', line 137

def community_channels(id:, user_id:)
  info!(event: "community:channels", id: id, user_id: user_id)

  community = ESM::Community.find_by(id: id)
  return if community.nil?

  server = community.discord_server

  user = ESM::User.find_by(id: user_id)

  # Get the channels the bot (and user if applicable) has access to
  channels = server.channels.filter_map do |channel|
    bot_can_read = ESM.bot.channel_permission?(:send_messages, channel)
    user_can_read = true
    user_can_read = user.channel_permission?(:read_messages, channel) if user
    next unless bot_can_read && user_can_read

    channel.to_h
  end

  # Now, we're going to make the order matter
  channels.sort_by! { |c| c[:position] || 0 }

  # Load all of the category channels into a hash where the key is their ID and the value is an empty array
  grouped_channels = channels.filter_map do |category_channel|
    next unless category_channel[:type] == :category

    children = channels.select do |channel|
      channel[:type] == :text && channel.dig(:category, :id) == category_channel[:id]
    end

    [category_channel, children]
  end

  # Organize the channels under their categories
  not_categorized_channels = channels.select { |channel| channel[:type] == :text && channel[:category].nil? }

  # Add a no category array to the front
  grouped_channels.unshift([{name: community.community_name}, not_categorized_channels])

  # Return the results
  grouped_channels
end

#community_delete(id:, user_id:) ⇒ Object

Deletes a community from the DB and forces ESM to leave it

Parameters:

  • id (String)

    The community's database ID

  • user_id (String)

    The user's database ID. Used to check if they have access



329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/esm/api.rb', line 329

def community_delete(id:, user_id:)
  info!(event: "community:delete", id: id, user_id: user_id)

  community = ESM::Community.where(id: id).first
  return if community.nil?

  user = ESM::User.where(id: user_id).first
  return if user.nil?

  discord_server = community.discord_server
  return if !community.modifiable_by?(user.discord_user.on(discord_server))

  discord_server.leave
  community.destroy
end

#community_modifiable_by?(id:, user_id:) ⇒ Boolean

Returns true/false if the user can modify this community

Parameters:

  • id (String)

    The community's database ID

  • user_id (String)

    The user's database ID

Returns:

  • (Boolean)


187
188
189
190
191
192
193
194
195
196
197
# File 'lib/esm/api.rb', line 187

def community_modifiable_by?(id:, user_id:)
  info!(event: "community:modifiable_by?", id: id, user_id: user_id)

  community = ESM::Community.find_by(id: id)
  return if community.nil? || community.discord_server.nil?

  user = ESM::User.find_by(id: user_id)
  return if user.nil?

  community.modifiable_by?(user.discord_user.on(community.discord_server))
end

#community_roles(id:) ⇒ Object

Returns the roles for the community

Parameters:

  • id (String)

    The community's database ID



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/esm/api.rb', line 204

def community_roles(id:)
  info!(event: "community:roles", id: id)

  community = ESM::Community.find_by(id: id)
  return if community.nil?

  server_roles = community.discord_server.roles
  return if server_roles.blank?

  server_roles.sort_by(&:position).reverse.filter_map do |role|
    next if role.permissions.administrator || role.name == "@everyone"

    {
      id: role.id.to_s,
      name: role.name,
      color: role.color.hex,
      disabled: false
    }
  end
end

#community_users(id:) ⇒ Object

Returns the users for the community

Parameters:

  • id (String)

    The community's database ID



230
231
232
233
234
235
236
237
238
239
240
# File 'lib/esm/api.rb', line 230

def community_users(id:)
  info!(event: "community:users", id: id)

  community = ESM::Community.find_by(id: id)
  return if community.nil?

  users = community.discord_server.users
  return if users.blank?

  users.map(&:to_h)
end

#requests_accept(id:) ⇒ Object

Accepts a request and triggers any logic that is required by the command



15
16
17
18
19
20
21
22
23
# File 'lib/esm/api.rb', line 15

def requests_accept(id:)
  info!(event: "requests:accept", id: id)

  request = ESM::Request.where(id: id).first
  return if request.nil?

  # Respond to the request
  request.respond(true)
end

#requests_decline(id:) ⇒ Object

Declines a request and triggers any logic that is required by the command



26
27
28
29
30
31
32
33
34
# File 'lib/esm/api.rb', line 26

def requests_decline(id:)
  info!(event: "requests:decline", id: id)

  request = ESM::Request.where(id: id).first
  return if request.nil?

  # Respond to the request
  request.respond(false)
end

#servers_connected(id:) ⇒ Object

Returns true if the server is connected



77
78
79
80
81
82
83
84
# File 'lib/esm/api.rb', line 77

def servers_connected(id:)
  info!(event: "servers:connected", id:)

  server = ESM::Server.find_by(id:)
  return if server.nil?

  server.connected?
end

#servers_reconnect(id:, old_id:) ⇒ Object

If a community changes their ID, their servers need to disconnect and reconnect id => New ID old_id => Old ID



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/esm/api.rb', line 60

def servers_reconnect(id:, old_id:)
  info!(event: "servers:reconnect", id: id, old_id: old_id)

  server = ESM::Server.where(id: id).first
  return if server.nil?
  return if old_id.blank?

  # Grab the old server connection
  connection = ESM::Websocket.connection(old_id)
  return if connection.nil?

  # Disconnect the old server. The DLL will automatically reconnect in 30 seconds
  # ESM::Websocket.remove_connection(connection)
  connection.connection.close(1000, "Server ID changed, reconnecting")
end

#servers_update(id:) ⇒ Object

Updates a server by sending it the initialization package again



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/esm/api.rb', line 37

def servers_update(id:)
  info!(event: "servers:update", id: id)

  server = ESM::Server.where(id: id).first
  return if server.nil?

  if server.v2?
    connection = server.connection
    return true if connection.nil?

    connection.close(I18n.t("server_reconnect.reasons.settings_update"))
  else
    connection = ESM::Websocket.connection(server.server_id)
    return true if connection.nil?

    # Tell ESM to update the server with the new details
    ESM::Event::ServerInitializationV1.new(connection: connection, server: server, parameters: {}).update
  end
end

#user_communities(id:, guild_ids:, check_for_perms: false) ⇒ Object

Returns an array of database IDs for the Community this user is part of

Parameters:

  • id (String)

    The user's database ID

  • guild_ids (true/false)

    The IDs of the guilds to check permissions



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/esm/api.rb', line 248

def user_communities(id:, guild_ids:, check_for_perms: false)
  info!(event: "user:communities", id:, guild_ids:, check_for_perms:)

  user = ESM::User.find_by(id: id)
  return if user.nil?

  communities = ESM::Community.select(
    :id, :guild_id, :dashboard_access_role_ids,
    :community_name, :player_mode_enabled, :icon_url
  ).where(guild_id: guild_ids)
  return [] if communities.blank?

  discord_user = user.discord_user
  communities.filter_map do |community|
    server = community.discord_server
    next if server.nil?

    # Keeps the community metadata up to date
    community.update(community_name: server.name, icon_url: server.icon_url)

    discord_member = discord_user.on(server)
    next if discord_member.nil?
    next if check_for_perms && !community.modifiable_by?(discord_member)

    community.id
  end
end

#user_community_permissions(id:, guild_ids:) ⇒ Array<Hash>

Returns community data with permission information for a user

Examples:

perms = Bot.user_community_permissions(123, ["guild1", "guild2"])
# => [
#   { id: 1, modifiable: true },
#   { id: 2, modifiable: false }
# ]

Parameters:

Returns:

  • (Array<Hash>)

    Array of community data with permission flags Each hash contains:

    • :id [Integer] The community's database ID
    • :modifiable [Boolean] Whether the user can modify this community


292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/esm/api.rb', line 292

def user_community_permissions(id:, guild_ids:)
  info!(event: "user:community_permissions", id:, guild_ids:)

  user = ESM::User.find_by(id: id)
  return if user.nil?

  communities = ESM::Community.select(
    :id, :guild_id, :dashboard_access_role_ids,
    :community_name, :player_mode_enabled, :icon_url
  ).where(guild_id: guild_ids)

  return [] if communities.blank?

  discord_user = user.discord_user
  communities.filter_map do |community|
    server = community.discord_server
    next if server.nil?

    # Keeps the community metadata up to date
    community.update(community_name: server.name, icon_url: server.icon_url)

    discord_member = discord_user.on(server)
    next if discord_member.nil?

    {
      id: community.id,
      modifiable: community.modifiable_by?(discord_member)
    }
  end
end