pub struct Cache {
pub guilds: RwLock<HashMap<Snowflake, Guild>>,
pub channels: RwLock<HashMap<Snowflake, Channel>>,
pub users: RwLock<HashMap<Snowflake, User>>,
pub current_user: RwLock<Option<User>>,
}Expand description
In-memory gateway cache.
Fields§
§guilds: RwLock<HashMap<Snowflake, Guild>>§channels: RwLock<HashMap<Snowflake, Channel>>§users: RwLock<HashMap<Snowflake, User>>§current_user: RwLock<Option<User>>Implementations§
Source§impl Cache
impl Cache
pub fn new() -> Arc<Self>
Sourcepub async fn guild(&self, id: &str) -> Option<Guild>
pub async fn guild(&self, id: &str) -> Option<Guild>
Looks up a guild by ID. Populated from GUILD_CREATE / GUILD_UPDATE events.
Sourcepub async fn channel(&self, id: &str) -> Option<Channel>
pub async fn channel(&self, id: &str) -> Option<Channel>
Looks up a channel by ID. Populated from GUILD_CREATE and CHANNEL_CREATE / CHANNEL_UPDATE events.
Examples found in repository?
examples/bot.rs (line 30)
28 async fn on_message(&self, ctx: Context, msg: Message) {
29 let user_cached = ctx.cache.user(&msg.author.id).await.is_some();
30 let ch_cached = ctx.cache.channel(msg.channel_id.as_deref().unwrap_or("")).await.is_some();
31 let content_preview = msg.content.as_deref().unwrap_or("").chars().take(60).collect::<String>();
32 let attachments = msg.attachments.as_ref().map(|a| a.len()).unwrap_or(0);
33 let embeds = msg.embeds.as_ref().map(|e| e.len()).unwrap_or(0);
34 println!(
35 "[msg] author={}#{} channel={} guild={} | \"{}\" | attach={} embeds={} | cache: user={} ch={}",
36 msg.author.username,
37 msg.author.discriminator.as_deref().unwrap_or("0"),
38 msg.channel_id.as_deref().unwrap_or("?"),
39 msg.guild_id.as_deref().unwrap_or("DM"),
40 content_preview,
41 attachments,
42 embeds,
43 user_cached,
44 ch_cached,
45 );
46
47 if msg.author.bot.unwrap_or(false) {
48 return;
49 }
50
51 let content = match msg.content.as_deref() {
52 Some(c) => c,
53 None => return,
54 };
55
56 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
57
58 let (cmd, args) = match parse_command(content) {
59 Some(v) => v,
60 None => return,
61 };
62
63 match cmd {
64 "ping" => {
65 let start = Instant::now();
66 let sent = ctx.http.send_message(channel_id, "Pong!").await;
67 let elapsed = start.elapsed().as_millis();
68
69 if let Ok(sent) = sent {
70 let _ = ctx.http.edit_message(
71 channel_id,
72 &sent.id,
73 &format!("Pong! {}ms", elapsed),
74 ).await;
75 }
76 }
77
78 "say" => {
79 if args.is_empty() {
80 let _ = ctx.http.send_message(channel_id, "Say what?").await;
81 return;
82 }
83 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
84 let _ = ctx.http.send_message(channel_id, args).await;
85 }
86
87 "embed" => {
88 let (title, desc) = match args.split_once('|') {
89 Some((t, d)) => (t.trim(), d.trim()),
90 None => {
91 let _ = ctx.http.send_message(channel_id, "`!embed title | description`").await;
92 return;
93 }
94 };
95
96 let embed = EmbedBuilder::new()
97 .title(title)
98 .description(desc)
99 .color(0x5865F2)
100 .build();
101
102 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
103 }
104
105 "react" => {
106 let _ = ctx.http.add_reaction(channel_id, &msg.id, "❤️").await;
107 }
108
109 "purge" => {
110 let count: u8 = args.parse().unwrap_or(0);
111 if count == 0 || count > 100 {
112 let _ = ctx.http.send_message(channel_id, "1-100.").await;
113 return;
114 }
115
116 let query = GetMessagesQuery {
117 limit: Some(count),
118 ..Default::default()
119 };
120
121 if let Ok(messages) = ctx.http.get_messages(channel_id, query).await {
122 let ids: Vec<&str> = messages.iter().map(|m| m.id.as_str()).collect();
123 let _ = ctx.http.bulk_delete_messages(channel_id, ids).await;
124 }
125 }
126
127 "serverinfo" => {
128 let guild_id = match &msg.guild_id {
129 Some(id) => id.as_str(),
130 None => return,
131 };
132
133 if let Ok(guild) = ctx.http.get_guild(guild_id).await {
134 let name = guild.name.as_deref().unwrap_or("Unknown");
135
136 let members = ctx.http.get_guild_members(guild_id, Some(1000), None).await
137 .map(|m| m.len().to_string())
138 .unwrap_or("?".into());
139
140 let embed = EmbedBuilder::new()
141 .title(name)
142 .field("Members", &members, true)
143 .color(0x5865F2)
144 .build();
145
146 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
147 }
148 }
149
150 "attach" => {
151 if args.is_empty() {
152 let _ = ctx.http.send_message(channel_id, "Usage: `!attach <file path>`").await;
153 return;
154 }
155 let path = std::path::Path::new(args);
156 let filename = path
157 .file_name()
158 .and_then(|n| n.to_str())
159 .unwrap_or("file")
160 .to_string();
161 let content_type = match path.extension().and_then(|e| e.to_str()) {
162 Some("mp3") => "audio/mpeg",
163 Some("mp4") => "video/mp4",
164 Some("mov") => "video/quicktime",
165 Some("webm") => "video/webm",
166 Some("png") => "image/png",
167 Some("jpg") | Some("jpeg") => "image/jpeg",
168 Some("gif") => "image/gif",
169 Some("webp") => "image/webp",
170 Some("txt") => "text/plain",
171 Some("pdf") => "application/pdf",
172 _ => "application/octet-stream",
173 };
174 match tokio::fs::read(path).await {
175 Ok(data) => {
176 let file = AttachmentFile {
177 filename,
178 data,
179 content_type: Some(content_type.to_string()),
180 };
181 match ctx.http.send_files(channel_id, vec![file], None).await {
182 Ok(msg) => println!("[attach] sent message {}", msg.id),
183 Err(e) => eprintln!("[attach] error: {}", e),
184 }
185 }
186 Err(e) => {
187 eprintln!("[attach] failed to read file: {}", e);
188 let _ = ctx.http.send_message(channel_id, &format!("Failed to read file: {}", e)).await;
189 }
190 }
191 }
192
193 _ => {}
194 }
195 }Sourcepub async fn user(&self, id: &str) -> Option<User>
pub async fn user(&self, id: &str) -> Option<User>
Looks up a user by ID. Populated from GUILD_CREATE member lists and MESSAGE_CREATE authors.
Examples found in repository?
examples/bot.rs (line 29)
28 async fn on_message(&self, ctx: Context, msg: Message) {
29 let user_cached = ctx.cache.user(&msg.author.id).await.is_some();
30 let ch_cached = ctx.cache.channel(msg.channel_id.as_deref().unwrap_or("")).await.is_some();
31 let content_preview = msg.content.as_deref().unwrap_or("").chars().take(60).collect::<String>();
32 let attachments = msg.attachments.as_ref().map(|a| a.len()).unwrap_or(0);
33 let embeds = msg.embeds.as_ref().map(|e| e.len()).unwrap_or(0);
34 println!(
35 "[msg] author={}#{} channel={} guild={} | \"{}\" | attach={} embeds={} | cache: user={} ch={}",
36 msg.author.username,
37 msg.author.discriminator.as_deref().unwrap_or("0"),
38 msg.channel_id.as_deref().unwrap_or("?"),
39 msg.guild_id.as_deref().unwrap_or("DM"),
40 content_preview,
41 attachments,
42 embeds,
43 user_cached,
44 ch_cached,
45 );
46
47 if msg.author.bot.unwrap_or(false) {
48 return;
49 }
50
51 let content = match msg.content.as_deref() {
52 Some(c) => c,
53 None => return,
54 };
55
56 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
57
58 let (cmd, args) = match parse_command(content) {
59 Some(v) => v,
60 None => return,
61 };
62
63 match cmd {
64 "ping" => {
65 let start = Instant::now();
66 let sent = ctx.http.send_message(channel_id, "Pong!").await;
67 let elapsed = start.elapsed().as_millis();
68
69 if let Ok(sent) = sent {
70 let _ = ctx.http.edit_message(
71 channel_id,
72 &sent.id,
73 &format!("Pong! {}ms", elapsed),
74 ).await;
75 }
76 }
77
78 "say" => {
79 if args.is_empty() {
80 let _ = ctx.http.send_message(channel_id, "Say what?").await;
81 return;
82 }
83 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
84 let _ = ctx.http.send_message(channel_id, args).await;
85 }
86
87 "embed" => {
88 let (title, desc) = match args.split_once('|') {
89 Some((t, d)) => (t.trim(), d.trim()),
90 None => {
91 let _ = ctx.http.send_message(channel_id, "`!embed title | description`").await;
92 return;
93 }
94 };
95
96 let embed = EmbedBuilder::new()
97 .title(title)
98 .description(desc)
99 .color(0x5865F2)
100 .build();
101
102 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
103 }
104
105 "react" => {
106 let _ = ctx.http.add_reaction(channel_id, &msg.id, "❤️").await;
107 }
108
109 "purge" => {
110 let count: u8 = args.parse().unwrap_or(0);
111 if count == 0 || count > 100 {
112 let _ = ctx.http.send_message(channel_id, "1-100.").await;
113 return;
114 }
115
116 let query = GetMessagesQuery {
117 limit: Some(count),
118 ..Default::default()
119 };
120
121 if let Ok(messages) = ctx.http.get_messages(channel_id, query).await {
122 let ids: Vec<&str> = messages.iter().map(|m| m.id.as_str()).collect();
123 let _ = ctx.http.bulk_delete_messages(channel_id, ids).await;
124 }
125 }
126
127 "serverinfo" => {
128 let guild_id = match &msg.guild_id {
129 Some(id) => id.as_str(),
130 None => return,
131 };
132
133 if let Ok(guild) = ctx.http.get_guild(guild_id).await {
134 let name = guild.name.as_deref().unwrap_or("Unknown");
135
136 let members = ctx.http.get_guild_members(guild_id, Some(1000), None).await
137 .map(|m| m.len().to_string())
138 .unwrap_or("?".into());
139
140 let embed = EmbedBuilder::new()
141 .title(name)
142 .field("Members", &members, true)
143 .color(0x5865F2)
144 .build();
145
146 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
147 }
148 }
149
150 "attach" => {
151 if args.is_empty() {
152 let _ = ctx.http.send_message(channel_id, "Usage: `!attach <file path>`").await;
153 return;
154 }
155 let path = std::path::Path::new(args);
156 let filename = path
157 .file_name()
158 .and_then(|n| n.to_str())
159 .unwrap_or("file")
160 .to_string();
161 let content_type = match path.extension().and_then(|e| e.to_str()) {
162 Some("mp3") => "audio/mpeg",
163 Some("mp4") => "video/mp4",
164 Some("mov") => "video/quicktime",
165 Some("webm") => "video/webm",
166 Some("png") => "image/png",
167 Some("jpg") | Some("jpeg") => "image/jpeg",
168 Some("gif") => "image/gif",
169 Some("webp") => "image/webp",
170 Some("txt") => "text/plain",
171 Some("pdf") => "application/pdf",
172 _ => "application/octet-stream",
173 };
174 match tokio::fs::read(path).await {
175 Ok(data) => {
176 let file = AttachmentFile {
177 filename,
178 data,
179 content_type: Some(content_type.to_string()),
180 };
181 match ctx.http.send_files(channel_id, vec![file], None).await {
182 Ok(msg) => println!("[attach] sent message {}", msg.id),
183 Err(e) => eprintln!("[attach] error: {}", e),
184 }
185 }
186 Err(e) => {
187 eprintln!("[attach] failed to read file: {}", e);
188 let _ = ctx.http.send_message(channel_id, &format!("Failed to read file: {}", e)).await;
189 }
190 }
191 }
192
193 _ => {}
194 }
195 }Sourcepub async fn current_user(&self) -> Option<User>
pub async fn current_user(&self) -> Option<User>
Returns the bot’s own User object, populated from the READY event.
Sourcepub async fn guild_count(&self) -> usize
pub async fn guild_count(&self) -> usize
Returns the number of guilds currently in cache.
Auto Trait Implementations§
impl !Freeze for Cache
impl !RefUnwindSafe for Cache
impl Send for Cache
impl Sync for Cache
impl Unpin for Cache
impl UnsafeUnpin for Cache
impl !UnwindSafe for Cache
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more