Module: Discordrb::Cache

Included in:
Bot
Defined in:
lib/discordrb/cache.rb

Overview

This mixin module does caching stuff for the library. It conveniently separates the logic behind the caching (like, storing the user hashes or making API calls to retrieve things) from the Bot that actually uses it.

Instance Method Summary collapse

Instance Method Details

#channel(id, server = nil) ⇒ Channel

Gets a channel given its ID. This queries the internal channel cache, and if the channel doesn't exist in there, it will get the data from Discord.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/discordrb/cache.rb', line 29

def channel(id, server = nil)
  id = id.resolve_id

  raise Discordrb::Errors::NoPermission if @restricted_channels.include? id

  debug("Obtaining data for channel with id #{id}")
  return @channels[id] if @channels[id]

  begin
    response = API.channel(token, id)
    channel = Channel.new(JSON.parse(response), self, server)
    @channels[id] = channel
  rescue Discordrb::Errors::NoPermission
    debug "Tried to get access to restricted channel #{id}, blacklisting it"
    @restricted_channels << id
    raise
  end
end

#ensure_channel(data) ⇒ Channel

Ensures a given channel object is cached and if not, cache it from the given data hash.



133
134
135
136
137
138
139
# File 'lib/discordrb/cache.rb', line 133

def ensure_channel(data)
  if @channels.include?(data['id'].to_i)
    @channels[data['id'].to_i]
  else
    @channels[data['id'].to_i] = Channel.new(data, self)
  end
end

#ensure_server(data) ⇒ Server

Ensures a given server object is cached and if not, cache it from the given data hash.



122
123
124
125
126
127
128
# File 'lib/discordrb/cache.rb', line 122

def ensure_server(data)
  if @servers.include?(data['id'].to_i)
    @servers[data['id'].to_i]
  else
    @servers[data['id'].to_i] = Server.new(data, self)
  end
end

#ensure_user(data) ⇒ User

Ensures a given user object is cached and if not, cache it from the given data hash.



111
112
113
114
115
116
117
# File 'lib/discordrb/cache.rb', line 111

def ensure_user(data)
  if @users.include?(data['id'].to_i)
    @users[data['id'].to_i]
  else
    @users[data['id'].to_i] = User.new(data, self)
  end
end

#find_channel(channel_name, server_name = nil, type: nil) ⇒ Array<Channel>

Finds a channel given its name and optionally the name of the server it is in.



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/discordrb/cache.rb', line 184

def find_channel(channel_name, server_name = nil, type: nil)
  results = []

  if /<#(?<id>\d+)>?/ =~ channel_name
    # Check for channel mentions separately
    return [channel(id)]
  end

  @servers.values.each do |server|
    server.channels.each do |channel|
      results << channel if channel.name == channel_name && (server_name || server.name) == server.name && (!type || (channel.type == type))
    end
  end

  results
end

#find_user(username) ⇒ Array<User>

Finds a user given its username.



204
205
206
# File 'lib/discordrb/cache.rb', line 204

def find_user(username)
  @users.values.find_all { |e| e.username == username }
end

#init_cacheObject

Initializes this cache



12
13
14
15
16
17
18
19
20
21
# File 'lib/discordrb/cache.rb', line 12

def init_cache
  @users = {}

  @servers = {}

  @channels = {}
  @private_channels = {}

  @restricted_channels = []
end

#invite(invite) ⇒ Invite

Gets information about an invite.



173
174
175
176
# File 'lib/discordrb/cache.rb', line 173

def invite(invite)
  code = resolve_invite_code(invite)
  Invite.new(JSON.parse(API.resolve_invite(token, code)), self)
end

#member(server_id, user_id) ⇒ Member?

Gets a member by both IDs



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/discordrb/cache.rb', line 80

def member(server_id, user_id)
  server_id = server_id.resolve_id
  user_id = user_id.resolve_id

  server = self.server(server_id)
  return server.member(user_id) if server.member_cached?(user_id)

  LOGGER.out("Resolving member #{server_id} on server #{user_id}")
  response = API.member(token, server_id, user_id)
  member = Member.new(JSON.parse(response), server, self)
  server.cache_member(member)
end

#private_channel(id) ⇒ Channel

Creates a private channel for the given user ID, or if one exists already, returns that one. It is recommended that you use User#pm instead, as this is mainly for internal use. However, usage of this method may be unavoidable if only the user ID is known.



98
99
100
101
102
103
104
105
106
# File 'lib/discordrb/cache.rb', line 98

def private_channel(id)
  id = id.resolve_id
  debug("Creating private channel with user id #{id}")
  return @private_channels[id] if @private_channels[id]

  response = API.create_private(token, @profile.id, id)
  channel = Channel.new(JSON.parse(response), self)
  @private_channels[id] = channel
end

#request_chunks(id) ⇒ Object

Requests member chunks for a given server ID.



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/discordrb/cache.rb', line 143

def request_chunks(id)
  chunk_packet = {
    op: 8,
    d: {
      guild_id: id,
      query: '',
      limit: 0
    }
  }.to_json
  @ws.send(chunk_packet)
end

#resolve_invite_code(invite) ⇒ String

Gets the code for an invite.



164
165
166
167
168
# File 'lib/discordrb/cache.rb', line 164

def resolve_invite_code(invite)
  invite = invite.code if invite.is_a? Discordrb::Invite
  invite = invite[invite.rindex('/') + 1..-1] if invite.start_with?('http', 'discord.gg')
  invite
end

#server(id) ⇒ Server?

Note:

This can only resolve servers the bot is currently in.

Gets a server by its ID.



66
67
68
69
70
71
72
73
74
# File 'lib/discordrb/cache.rb', line 66

def server(id)
  id = id.resolve_id
  return @servers[id] if @servers[id]

  LOGGER.out("Resolving server #{id}")
  response = API.server(token, id)
  server = Server.new(JSON.parse(response), self)
  @servers[id] = server
end

#user(id) ⇒ User?

Note:

This can only resolve users known by the bot (i.e. that share a server with the bot).

Gets a user by its ID.



52
53
54
55
56
57
58
59
60
# File 'lib/discordrb/cache.rb', line 52

def user(id)
  id = id.resolve_id
  return @users[id] if @users[id]

  LOGGER.out("Resolving user #{id}")
  response = API.user(token, id)
  user = User.new(JSON.parse(response), self)
  @users[id] = user
end