pub struct EmbedBuilder(/* private fields */);Expand description
Builder for Embed. Chain methods and call .build() at the end.
use fluxer::prelude::*;
let embed = EmbedBuilder::new()
.title("Hello")
.description("World")
.color(0x00FF00)
.build();Implementations§
Source§impl EmbedBuilder
impl EmbedBuilder
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
examples/selfbot.rs (line 128)
28 async fn on_message(&self, ctx: Context, msg: Message) {
29 if !is_me(&ctx, &msg).await {
30 return;
31 }
32
33 let content = match msg.content.as_deref() {
34 Some(c) => c,
35 None => return,
36 };
37
38 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
39
40 let (cmd, args) = match parse_command(content) {
41 Some(v) => v,
42 None => return,
43 };
44
45 match cmd {
46 "ping" => {
47 let start = Instant::now();
48 let sent = ctx.http.send_message(channel_id, "Pong!").await;
49 let elapsed = start.elapsed().as_millis();
50 if let Ok(sent) = sent {
51 let _ = ctx.http.edit_message(
52 channel_id,
53 &sent.id,
54 &format!("Pong! `{}ms`", elapsed),
55 ).await;
56 }
57 }
58
59 "8ball" => {
60 if args.is_empty() {
61 let _ = ctx.http.edit_message(channel_id, &msg.id, "Ask a question!").await;
62 return;
63 }
64 let responses = [
65 "Yes", "No", "Maybe", "Definitely", "Absolutely not",
66 "Ask again later", "Better not tell you now", "Cannot predict now",
67 "Don't count on it", "It is certain", "Most likely", "Outlook good",
68 "Reply hazy, try again", "Signs point to yes", "Very doubtful", "Without a doubt",
69 ];
70 let idx = (std::time::SystemTime::now()
71 .duration_since(std::time::UNIX_EPOCH)
72 .unwrap()
73 .as_nanos() % responses.len() as u128) as usize;
74 let answer = responses[idx];
75 let _ = ctx.http.edit_message(channel_id, &msg.id, answer).await;
76 }
77
78 "flip" => {
79 let result = if std::time::SystemTime::now()
80 .duration_since(std::time::UNIX_EPOCH)
81 .unwrap()
82 .as_nanos().is_multiple_of(2) { "Heads" } else { "Tails" };
83 let _ = ctx.http.edit_message(channel_id, &msg.id, result).await;
84 }
85
86 "roll" => {
87 let sides: u32 = args.parse().unwrap_or(6);
88 if !(2..=100).contains(&sides) {
89 let _ = ctx.http.edit_message(channel_id, &msg.id, "Use 2-100 sides").await;
90 return;
91 }
92 let result = (std::time::SystemTime::now()
93 .duration_since(std::time::UNIX_EPOCH)
94 .unwrap()
95 .as_nanos() % sides as u128) as u32 + 1;
96 let _ = ctx.http.edit_message(channel_id, &msg.id, &format!("Rolled {}/{}", result, sides)).await;
97 }
98
99 "purge" => {
100 let count: u8 = args.parse().unwrap_or(10).min(100);
101 let query = GetMessagesQuery {
102 limit: Some(count),
103 before: None,
104 after: None,
105 around: None,
106 };
107 match ctx.http.get_messages(channel_id, query).await {
108 Ok(messages) => {
109 let my_id = ctx.cache.current_user().await.map(|u| u.id).unwrap_or_default();
110 let my_messages: Vec<_> = messages.iter()
111 .filter(|m| m.author.id == my_id)
112 .map(|m| m.id.as_str())
113 .collect();
114
115 if !my_messages.is_empty() {
116 let _ = ctx.http.bulk_delete_messages(channel_id, my_messages).await;
117 }
118 }
119 Err(e) => eprintln!("[purge] failed: {}", e),
120 }
121 }
122
123 "embed" => {
124 if args.is_empty() {
125 let _ = ctx.http.edit_message(channel_id, &msg.id, "Usage: sb!embed <text>").await;
126 return;
127 }
128 let embed = EmbedBuilder::new()
129 .description(args)
130 .color(0x5865F2)
131 .build();
132
133 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
134 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
135 }
136
137 "edit" => {
138 if args.is_empty() { return; }
139 let _ = ctx.http.edit_message(channel_id, &msg.id, args).await;
140 }
141
142 "help" => {
143 let help_text = "**Selfbot Commands**\n\
144 `sb!ping` - Check latency\n\
145 `sb!8ball <question>` - Ask the magic 8ball\n\
146 `sb!flip` - Flip a coin\n\
147 `sb!roll [sides]` - Roll a die (default 6)\n\
148 `sb!purge [count]` - Delete your recent messages\n\
149 `sb!embed <text>` - Send an embed\n\
150 `sb!edit <text>` - Edit your message\n\
151 `sb!help` - Show this message";
152 let _ = ctx.http.edit_message(channel_id, &msg.id, help_text).await;
153 }
154
155 _ => {}
156 }
157 }More examples
examples/bot.rs (line 95)
27 async fn on_message(&self, ctx: Context, msg: Message) {
28 let user_cached = ctx.cache.user(&msg.author.id).await.is_some();
29 let ch_cached = ctx.cache.channel(msg.channel_id.as_deref().unwrap_or("")).await.is_some();
30 let content_preview = msg.content.as_deref().unwrap_or("").chars().take(60).collect::<String>();
31 let attachments = msg.attachments.as_ref().map(|a| a.len()).unwrap_or(0);
32 let embeds = msg.embeds.as_ref().map(|e| e.len()).unwrap_or(0);
33 println!(
34 "[msg] author={}#{} channel={} guild={} | \"{}\" | attach={} embeds={} | cache: user={} ch={}",
35 msg.author.username,
36 msg.author.discriminator.as_deref().unwrap_or("0"),
37 msg.channel_id.as_deref().unwrap_or("?"),
38 msg.guild_id.as_deref().unwrap_or("DM"),
39 content_preview,
40 attachments,
41 embeds,
42 user_cached,
43 ch_cached,
44 );
45
46 if msg.author.bot.unwrap_or(false) {
47 return;
48 }
49
50 let content = match msg.content.as_deref() {
51 Some(c) => c,
52 None => return,
53 };
54
55 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
56
57 let (cmd, args) = match parse_command(content) {
58 Some(v) => v,
59 None => return,
60 };
61
62 match cmd {
63 "ping" => {
64 let start = Instant::now();
65 let sent = ctx.http.send_message(channel_id, "Pong!").await;
66 let elapsed = start.elapsed().as_millis();
67
68 if let Ok(sent) = sent {
69 let _ = ctx.http.edit_message(
70 channel_id,
71 &sent.id,
72 &format!("Pong! {}ms", elapsed),
73 ).await;
74 }
75 }
76
77 "say" => {
78 if args.is_empty() {
79 let _ = ctx.http.send_message(channel_id, "Say what?").await;
80 return;
81 }
82 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
83 let _ = ctx.http.send_message(channel_id, args).await;
84 }
85
86 "embed" => {
87 let (title, desc) = match args.split_once('|') {
88 Some((t, d)) => (t.trim(), d.trim()),
89 None => {
90 let _ = ctx.http.send_message(channel_id, "`!embed title | description`").await;
91 return;
92 }
93 };
94
95 let embed = EmbedBuilder::new()
96 .title(title)
97 .description(desc)
98 .color(0x5865F2)
99 .build();
100
101 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
102 }
103
104 "react" => {
105 let _ = ctx.http.add_reaction(channel_id, &msg.id, "❤️").await;
106 }
107
108 "purge" => {
109 let count: u8 = args.parse().unwrap_or(0);
110 if count == 0 || count > 100 {
111 let _ = ctx.http.send_message(channel_id, "1-100.").await;
112 return;
113 }
114
115 let query = GetMessagesQuery {
116 limit: Some(count),
117 ..Default::default()
118 };
119
120 if let Ok(messages) = ctx.http.get_messages(channel_id, query).await {
121 let ids: Vec<&str> = messages.iter().map(|m| m.id.as_str()).collect();
122 let _ = ctx.http.bulk_delete_messages(channel_id, ids).await;
123 }
124 }
125
126 "serverinfo" => {
127 let guild_id = match &msg.guild_id {
128 Some(id) => id.as_str(),
129 None => return,
130 };
131
132 if let Ok(guild) = ctx.http.get_guild(guild_id).await {
133 let name = guild.name.as_deref().unwrap_or("Unknown");
134
135 let members = ctx.http.get_guild_members(guild_id, Some(1000), None).await
136 .map(|m| m.len().to_string())
137 .unwrap_or("?".into());
138
139 let embed = EmbedBuilder::new()
140 .title(name)
141 .field("Members", &members, true)
142 .color(0x5865F2)
143 .build();
144
145 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
146 }
147 }
148
149 "attach" => {
150 if args.is_empty() {
151 let _ = ctx.http.send_message(channel_id, "Usage: `!attach <file path>`").await;
152 return;
153 }
154 let path = std::path::Path::new(args);
155 let filename = path
156 .file_name()
157 .and_then(|n| n.to_str())
158 .unwrap_or("file")
159 .to_string();
160 let content_type = match path.extension().and_then(|e| e.to_str()) {
161 Some("mp3") => "audio/mpeg",
162 Some("mp4") => "video/mp4",
163 Some("mov") => "video/quicktime",
164 Some("webm") => "video/webm",
165 Some("png") => "image/png",
166 Some("jpg") | Some("jpeg") => "image/jpeg",
167 Some("gif") => "image/gif",
168 Some("webp") => "image/webp",
169 Some("txt") => "text/plain",
170 Some("pdf") => "application/pdf",
171 _ => "application/octet-stream",
172 };
173 match tokio::fs::read(path).await {
174 Ok(data) => {
175 let file = AttachmentFile {
176 filename,
177 data,
178 content_type: Some(content_type.to_string()),
179 };
180 match ctx.http.send_files(channel_id, vec![file], None).await {
181 Ok(msg) => println!("[attach] sent message {}", msg.id),
182 Err(e) => eprintln!("[attach] error: {}", e),
183 }
184 }
185 Err(e) => {
186 eprintln!("[attach] failed to read file: {}", e);
187 let _ = ctx.http.send_message(channel_id, &format!("Failed to read file: {}", e)).await;
188 }
189 }
190 }
191
192 "addrole" => {
193 let guild_id = match &msg.guild_id {
194 Some(id) => id.as_str(),
195 None => return,
196 };
197 let parts: Vec<&str> = args.split_whitespace().collect();
198 if parts.len() != 2 {
199 let _ = ctx.http.send_message(channel_id, "Usage: `!addrole <user_id> <role_id>`").await;
200 return;
201 }
202 match ctx.http.add_member_role(guild_id, parts[0], parts[1]).await {
203 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role added").await; }
204 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
205 }
206 }
207
208 "removerole" => {
209 let guild_id = match &msg.guild_id {
210 Some(id) => id.as_str(),
211 None => return,
212 };
213 let parts: Vec<&str> = args.split_whitespace().collect();
214 if parts.len() != 2 {
215 let _ = ctx.http.send_message(channel_id, "Usage: `!removerole <user_id> <role_id>`").await;
216 return;
217 }
218 match ctx.http.remove_member_role(guild_id, parts[0], parts[1]).await {
219 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role removed").await; }
220 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
221 }
222 }
223
224 _ => {}
225 }
226 }Sourcepub fn title(self, title: impl Into<String>) -> Self
pub fn title(self, title: impl Into<String>) -> Self
Examples found in repository?
examples/bot.rs (line 96)
27 async fn on_message(&self, ctx: Context, msg: Message) {
28 let user_cached = ctx.cache.user(&msg.author.id).await.is_some();
29 let ch_cached = ctx.cache.channel(msg.channel_id.as_deref().unwrap_or("")).await.is_some();
30 let content_preview = msg.content.as_deref().unwrap_or("").chars().take(60).collect::<String>();
31 let attachments = msg.attachments.as_ref().map(|a| a.len()).unwrap_or(0);
32 let embeds = msg.embeds.as_ref().map(|e| e.len()).unwrap_or(0);
33 println!(
34 "[msg] author={}#{} channel={} guild={} | \"{}\" | attach={} embeds={} | cache: user={} ch={}",
35 msg.author.username,
36 msg.author.discriminator.as_deref().unwrap_or("0"),
37 msg.channel_id.as_deref().unwrap_or("?"),
38 msg.guild_id.as_deref().unwrap_or("DM"),
39 content_preview,
40 attachments,
41 embeds,
42 user_cached,
43 ch_cached,
44 );
45
46 if msg.author.bot.unwrap_or(false) {
47 return;
48 }
49
50 let content = match msg.content.as_deref() {
51 Some(c) => c,
52 None => return,
53 };
54
55 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
56
57 let (cmd, args) = match parse_command(content) {
58 Some(v) => v,
59 None => return,
60 };
61
62 match cmd {
63 "ping" => {
64 let start = Instant::now();
65 let sent = ctx.http.send_message(channel_id, "Pong!").await;
66 let elapsed = start.elapsed().as_millis();
67
68 if let Ok(sent) = sent {
69 let _ = ctx.http.edit_message(
70 channel_id,
71 &sent.id,
72 &format!("Pong! {}ms", elapsed),
73 ).await;
74 }
75 }
76
77 "say" => {
78 if args.is_empty() {
79 let _ = ctx.http.send_message(channel_id, "Say what?").await;
80 return;
81 }
82 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
83 let _ = ctx.http.send_message(channel_id, args).await;
84 }
85
86 "embed" => {
87 let (title, desc) = match args.split_once('|') {
88 Some((t, d)) => (t.trim(), d.trim()),
89 None => {
90 let _ = ctx.http.send_message(channel_id, "`!embed title | description`").await;
91 return;
92 }
93 };
94
95 let embed = EmbedBuilder::new()
96 .title(title)
97 .description(desc)
98 .color(0x5865F2)
99 .build();
100
101 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
102 }
103
104 "react" => {
105 let _ = ctx.http.add_reaction(channel_id, &msg.id, "❤️").await;
106 }
107
108 "purge" => {
109 let count: u8 = args.parse().unwrap_or(0);
110 if count == 0 || count > 100 {
111 let _ = ctx.http.send_message(channel_id, "1-100.").await;
112 return;
113 }
114
115 let query = GetMessagesQuery {
116 limit: Some(count),
117 ..Default::default()
118 };
119
120 if let Ok(messages) = ctx.http.get_messages(channel_id, query).await {
121 let ids: Vec<&str> = messages.iter().map(|m| m.id.as_str()).collect();
122 let _ = ctx.http.bulk_delete_messages(channel_id, ids).await;
123 }
124 }
125
126 "serverinfo" => {
127 let guild_id = match &msg.guild_id {
128 Some(id) => id.as_str(),
129 None => return,
130 };
131
132 if let Ok(guild) = ctx.http.get_guild(guild_id).await {
133 let name = guild.name.as_deref().unwrap_or("Unknown");
134
135 let members = ctx.http.get_guild_members(guild_id, Some(1000), None).await
136 .map(|m| m.len().to_string())
137 .unwrap_or("?".into());
138
139 let embed = EmbedBuilder::new()
140 .title(name)
141 .field("Members", &members, true)
142 .color(0x5865F2)
143 .build();
144
145 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
146 }
147 }
148
149 "attach" => {
150 if args.is_empty() {
151 let _ = ctx.http.send_message(channel_id, "Usage: `!attach <file path>`").await;
152 return;
153 }
154 let path = std::path::Path::new(args);
155 let filename = path
156 .file_name()
157 .and_then(|n| n.to_str())
158 .unwrap_or("file")
159 .to_string();
160 let content_type = match path.extension().and_then(|e| e.to_str()) {
161 Some("mp3") => "audio/mpeg",
162 Some("mp4") => "video/mp4",
163 Some("mov") => "video/quicktime",
164 Some("webm") => "video/webm",
165 Some("png") => "image/png",
166 Some("jpg") | Some("jpeg") => "image/jpeg",
167 Some("gif") => "image/gif",
168 Some("webp") => "image/webp",
169 Some("txt") => "text/plain",
170 Some("pdf") => "application/pdf",
171 _ => "application/octet-stream",
172 };
173 match tokio::fs::read(path).await {
174 Ok(data) => {
175 let file = AttachmentFile {
176 filename,
177 data,
178 content_type: Some(content_type.to_string()),
179 };
180 match ctx.http.send_files(channel_id, vec![file], None).await {
181 Ok(msg) => println!("[attach] sent message {}", msg.id),
182 Err(e) => eprintln!("[attach] error: {}", e),
183 }
184 }
185 Err(e) => {
186 eprintln!("[attach] failed to read file: {}", e);
187 let _ = ctx.http.send_message(channel_id, &format!("Failed to read file: {}", e)).await;
188 }
189 }
190 }
191
192 "addrole" => {
193 let guild_id = match &msg.guild_id {
194 Some(id) => id.as_str(),
195 None => return,
196 };
197 let parts: Vec<&str> = args.split_whitespace().collect();
198 if parts.len() != 2 {
199 let _ = ctx.http.send_message(channel_id, "Usage: `!addrole <user_id> <role_id>`").await;
200 return;
201 }
202 match ctx.http.add_member_role(guild_id, parts[0], parts[1]).await {
203 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role added").await; }
204 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
205 }
206 }
207
208 "removerole" => {
209 let guild_id = match &msg.guild_id {
210 Some(id) => id.as_str(),
211 None => return,
212 };
213 let parts: Vec<&str> = args.split_whitespace().collect();
214 if parts.len() != 2 {
215 let _ = ctx.http.send_message(channel_id, "Usage: `!removerole <user_id> <role_id>`").await;
216 return;
217 }
218 match ctx.http.remove_member_role(guild_id, parts[0], parts[1]).await {
219 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role removed").await; }
220 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
221 }
222 }
223
224 _ => {}
225 }
226 }Sourcepub fn description(self, desc: impl Into<String>) -> Self
pub fn description(self, desc: impl Into<String>) -> Self
Examples found in repository?
examples/selfbot.rs (line 129)
28 async fn on_message(&self, ctx: Context, msg: Message) {
29 if !is_me(&ctx, &msg).await {
30 return;
31 }
32
33 let content = match msg.content.as_deref() {
34 Some(c) => c,
35 None => return,
36 };
37
38 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
39
40 let (cmd, args) = match parse_command(content) {
41 Some(v) => v,
42 None => return,
43 };
44
45 match cmd {
46 "ping" => {
47 let start = Instant::now();
48 let sent = ctx.http.send_message(channel_id, "Pong!").await;
49 let elapsed = start.elapsed().as_millis();
50 if let Ok(sent) = sent {
51 let _ = ctx.http.edit_message(
52 channel_id,
53 &sent.id,
54 &format!("Pong! `{}ms`", elapsed),
55 ).await;
56 }
57 }
58
59 "8ball" => {
60 if args.is_empty() {
61 let _ = ctx.http.edit_message(channel_id, &msg.id, "Ask a question!").await;
62 return;
63 }
64 let responses = [
65 "Yes", "No", "Maybe", "Definitely", "Absolutely not",
66 "Ask again later", "Better not tell you now", "Cannot predict now",
67 "Don't count on it", "It is certain", "Most likely", "Outlook good",
68 "Reply hazy, try again", "Signs point to yes", "Very doubtful", "Without a doubt",
69 ];
70 let idx = (std::time::SystemTime::now()
71 .duration_since(std::time::UNIX_EPOCH)
72 .unwrap()
73 .as_nanos() % responses.len() as u128) as usize;
74 let answer = responses[idx];
75 let _ = ctx.http.edit_message(channel_id, &msg.id, answer).await;
76 }
77
78 "flip" => {
79 let result = if std::time::SystemTime::now()
80 .duration_since(std::time::UNIX_EPOCH)
81 .unwrap()
82 .as_nanos().is_multiple_of(2) { "Heads" } else { "Tails" };
83 let _ = ctx.http.edit_message(channel_id, &msg.id, result).await;
84 }
85
86 "roll" => {
87 let sides: u32 = args.parse().unwrap_or(6);
88 if !(2..=100).contains(&sides) {
89 let _ = ctx.http.edit_message(channel_id, &msg.id, "Use 2-100 sides").await;
90 return;
91 }
92 let result = (std::time::SystemTime::now()
93 .duration_since(std::time::UNIX_EPOCH)
94 .unwrap()
95 .as_nanos() % sides as u128) as u32 + 1;
96 let _ = ctx.http.edit_message(channel_id, &msg.id, &format!("Rolled {}/{}", result, sides)).await;
97 }
98
99 "purge" => {
100 let count: u8 = args.parse().unwrap_or(10).min(100);
101 let query = GetMessagesQuery {
102 limit: Some(count),
103 before: None,
104 after: None,
105 around: None,
106 };
107 match ctx.http.get_messages(channel_id, query).await {
108 Ok(messages) => {
109 let my_id = ctx.cache.current_user().await.map(|u| u.id).unwrap_or_default();
110 let my_messages: Vec<_> = messages.iter()
111 .filter(|m| m.author.id == my_id)
112 .map(|m| m.id.as_str())
113 .collect();
114
115 if !my_messages.is_empty() {
116 let _ = ctx.http.bulk_delete_messages(channel_id, my_messages).await;
117 }
118 }
119 Err(e) => eprintln!("[purge] failed: {}", e),
120 }
121 }
122
123 "embed" => {
124 if args.is_empty() {
125 let _ = ctx.http.edit_message(channel_id, &msg.id, "Usage: sb!embed <text>").await;
126 return;
127 }
128 let embed = EmbedBuilder::new()
129 .description(args)
130 .color(0x5865F2)
131 .build();
132
133 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
134 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
135 }
136
137 "edit" => {
138 if args.is_empty() { return; }
139 let _ = ctx.http.edit_message(channel_id, &msg.id, args).await;
140 }
141
142 "help" => {
143 let help_text = "**Selfbot Commands**\n\
144 `sb!ping` - Check latency\n\
145 `sb!8ball <question>` - Ask the magic 8ball\n\
146 `sb!flip` - Flip a coin\n\
147 `sb!roll [sides]` - Roll a die (default 6)\n\
148 `sb!purge [count]` - Delete your recent messages\n\
149 `sb!embed <text>` - Send an embed\n\
150 `sb!edit <text>` - Edit your message\n\
151 `sb!help` - Show this message";
152 let _ = ctx.http.edit_message(channel_id, &msg.id, help_text).await;
153 }
154
155 _ => {}
156 }
157 }More examples
examples/bot.rs (line 97)
27 async fn on_message(&self, ctx: Context, msg: Message) {
28 let user_cached = ctx.cache.user(&msg.author.id).await.is_some();
29 let ch_cached = ctx.cache.channel(msg.channel_id.as_deref().unwrap_or("")).await.is_some();
30 let content_preview = msg.content.as_deref().unwrap_or("").chars().take(60).collect::<String>();
31 let attachments = msg.attachments.as_ref().map(|a| a.len()).unwrap_or(0);
32 let embeds = msg.embeds.as_ref().map(|e| e.len()).unwrap_or(0);
33 println!(
34 "[msg] author={}#{} channel={} guild={} | \"{}\" | attach={} embeds={} | cache: user={} ch={}",
35 msg.author.username,
36 msg.author.discriminator.as_deref().unwrap_or("0"),
37 msg.channel_id.as_deref().unwrap_or("?"),
38 msg.guild_id.as_deref().unwrap_or("DM"),
39 content_preview,
40 attachments,
41 embeds,
42 user_cached,
43 ch_cached,
44 );
45
46 if msg.author.bot.unwrap_or(false) {
47 return;
48 }
49
50 let content = match msg.content.as_deref() {
51 Some(c) => c,
52 None => return,
53 };
54
55 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
56
57 let (cmd, args) = match parse_command(content) {
58 Some(v) => v,
59 None => return,
60 };
61
62 match cmd {
63 "ping" => {
64 let start = Instant::now();
65 let sent = ctx.http.send_message(channel_id, "Pong!").await;
66 let elapsed = start.elapsed().as_millis();
67
68 if let Ok(sent) = sent {
69 let _ = ctx.http.edit_message(
70 channel_id,
71 &sent.id,
72 &format!("Pong! {}ms", elapsed),
73 ).await;
74 }
75 }
76
77 "say" => {
78 if args.is_empty() {
79 let _ = ctx.http.send_message(channel_id, "Say what?").await;
80 return;
81 }
82 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
83 let _ = ctx.http.send_message(channel_id, args).await;
84 }
85
86 "embed" => {
87 let (title, desc) = match args.split_once('|') {
88 Some((t, d)) => (t.trim(), d.trim()),
89 None => {
90 let _ = ctx.http.send_message(channel_id, "`!embed title | description`").await;
91 return;
92 }
93 };
94
95 let embed = EmbedBuilder::new()
96 .title(title)
97 .description(desc)
98 .color(0x5865F2)
99 .build();
100
101 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
102 }
103
104 "react" => {
105 let _ = ctx.http.add_reaction(channel_id, &msg.id, "❤️").await;
106 }
107
108 "purge" => {
109 let count: u8 = args.parse().unwrap_or(0);
110 if count == 0 || count > 100 {
111 let _ = ctx.http.send_message(channel_id, "1-100.").await;
112 return;
113 }
114
115 let query = GetMessagesQuery {
116 limit: Some(count),
117 ..Default::default()
118 };
119
120 if let Ok(messages) = ctx.http.get_messages(channel_id, query).await {
121 let ids: Vec<&str> = messages.iter().map(|m| m.id.as_str()).collect();
122 let _ = ctx.http.bulk_delete_messages(channel_id, ids).await;
123 }
124 }
125
126 "serverinfo" => {
127 let guild_id = match &msg.guild_id {
128 Some(id) => id.as_str(),
129 None => return,
130 };
131
132 if let Ok(guild) = ctx.http.get_guild(guild_id).await {
133 let name = guild.name.as_deref().unwrap_or("Unknown");
134
135 let members = ctx.http.get_guild_members(guild_id, Some(1000), None).await
136 .map(|m| m.len().to_string())
137 .unwrap_or("?".into());
138
139 let embed = EmbedBuilder::new()
140 .title(name)
141 .field("Members", &members, true)
142 .color(0x5865F2)
143 .build();
144
145 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
146 }
147 }
148
149 "attach" => {
150 if args.is_empty() {
151 let _ = ctx.http.send_message(channel_id, "Usage: `!attach <file path>`").await;
152 return;
153 }
154 let path = std::path::Path::new(args);
155 let filename = path
156 .file_name()
157 .and_then(|n| n.to_str())
158 .unwrap_or("file")
159 .to_string();
160 let content_type = match path.extension().and_then(|e| e.to_str()) {
161 Some("mp3") => "audio/mpeg",
162 Some("mp4") => "video/mp4",
163 Some("mov") => "video/quicktime",
164 Some("webm") => "video/webm",
165 Some("png") => "image/png",
166 Some("jpg") | Some("jpeg") => "image/jpeg",
167 Some("gif") => "image/gif",
168 Some("webp") => "image/webp",
169 Some("txt") => "text/plain",
170 Some("pdf") => "application/pdf",
171 _ => "application/octet-stream",
172 };
173 match tokio::fs::read(path).await {
174 Ok(data) => {
175 let file = AttachmentFile {
176 filename,
177 data,
178 content_type: Some(content_type.to_string()),
179 };
180 match ctx.http.send_files(channel_id, vec![file], None).await {
181 Ok(msg) => println!("[attach] sent message {}", msg.id),
182 Err(e) => eprintln!("[attach] error: {}", e),
183 }
184 }
185 Err(e) => {
186 eprintln!("[attach] failed to read file: {}", e);
187 let _ = ctx.http.send_message(channel_id, &format!("Failed to read file: {}", e)).await;
188 }
189 }
190 }
191
192 "addrole" => {
193 let guild_id = match &msg.guild_id {
194 Some(id) => id.as_str(),
195 None => return,
196 };
197 let parts: Vec<&str> = args.split_whitespace().collect();
198 if parts.len() != 2 {
199 let _ = ctx.http.send_message(channel_id, "Usage: `!addrole <user_id> <role_id>`").await;
200 return;
201 }
202 match ctx.http.add_member_role(guild_id, parts[0], parts[1]).await {
203 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role added").await; }
204 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
205 }
206 }
207
208 "removerole" => {
209 let guild_id = match &msg.guild_id {
210 Some(id) => id.as_str(),
211 None => return,
212 };
213 let parts: Vec<&str> = args.split_whitespace().collect();
214 if parts.len() != 2 {
215 let _ = ctx.http.send_message(channel_id, "Usage: `!removerole <user_id> <role_id>`").await;
216 return;
217 }
218 match ctx.http.remove_member_role(guild_id, parts[0], parts[1]).await {
219 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role removed").await; }
220 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
221 }
222 }
223
224 _ => {}
225 }
226 }pub fn url(self, url: impl Into<String>) -> Self
Sourcepub fn color(self, color: u64) -> Self
pub fn color(self, color: u64) -> Self
Examples found in repository?
examples/selfbot.rs (line 130)
28 async fn on_message(&self, ctx: Context, msg: Message) {
29 if !is_me(&ctx, &msg).await {
30 return;
31 }
32
33 let content = match msg.content.as_deref() {
34 Some(c) => c,
35 None => return,
36 };
37
38 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
39
40 let (cmd, args) = match parse_command(content) {
41 Some(v) => v,
42 None => return,
43 };
44
45 match cmd {
46 "ping" => {
47 let start = Instant::now();
48 let sent = ctx.http.send_message(channel_id, "Pong!").await;
49 let elapsed = start.elapsed().as_millis();
50 if let Ok(sent) = sent {
51 let _ = ctx.http.edit_message(
52 channel_id,
53 &sent.id,
54 &format!("Pong! `{}ms`", elapsed),
55 ).await;
56 }
57 }
58
59 "8ball" => {
60 if args.is_empty() {
61 let _ = ctx.http.edit_message(channel_id, &msg.id, "Ask a question!").await;
62 return;
63 }
64 let responses = [
65 "Yes", "No", "Maybe", "Definitely", "Absolutely not",
66 "Ask again later", "Better not tell you now", "Cannot predict now",
67 "Don't count on it", "It is certain", "Most likely", "Outlook good",
68 "Reply hazy, try again", "Signs point to yes", "Very doubtful", "Without a doubt",
69 ];
70 let idx = (std::time::SystemTime::now()
71 .duration_since(std::time::UNIX_EPOCH)
72 .unwrap()
73 .as_nanos() % responses.len() as u128) as usize;
74 let answer = responses[idx];
75 let _ = ctx.http.edit_message(channel_id, &msg.id, answer).await;
76 }
77
78 "flip" => {
79 let result = if std::time::SystemTime::now()
80 .duration_since(std::time::UNIX_EPOCH)
81 .unwrap()
82 .as_nanos().is_multiple_of(2) { "Heads" } else { "Tails" };
83 let _ = ctx.http.edit_message(channel_id, &msg.id, result).await;
84 }
85
86 "roll" => {
87 let sides: u32 = args.parse().unwrap_or(6);
88 if !(2..=100).contains(&sides) {
89 let _ = ctx.http.edit_message(channel_id, &msg.id, "Use 2-100 sides").await;
90 return;
91 }
92 let result = (std::time::SystemTime::now()
93 .duration_since(std::time::UNIX_EPOCH)
94 .unwrap()
95 .as_nanos() % sides as u128) as u32 + 1;
96 let _ = ctx.http.edit_message(channel_id, &msg.id, &format!("Rolled {}/{}", result, sides)).await;
97 }
98
99 "purge" => {
100 let count: u8 = args.parse().unwrap_or(10).min(100);
101 let query = GetMessagesQuery {
102 limit: Some(count),
103 before: None,
104 after: None,
105 around: None,
106 };
107 match ctx.http.get_messages(channel_id, query).await {
108 Ok(messages) => {
109 let my_id = ctx.cache.current_user().await.map(|u| u.id).unwrap_or_default();
110 let my_messages: Vec<_> = messages.iter()
111 .filter(|m| m.author.id == my_id)
112 .map(|m| m.id.as_str())
113 .collect();
114
115 if !my_messages.is_empty() {
116 let _ = ctx.http.bulk_delete_messages(channel_id, my_messages).await;
117 }
118 }
119 Err(e) => eprintln!("[purge] failed: {}", e),
120 }
121 }
122
123 "embed" => {
124 if args.is_empty() {
125 let _ = ctx.http.edit_message(channel_id, &msg.id, "Usage: sb!embed <text>").await;
126 return;
127 }
128 let embed = EmbedBuilder::new()
129 .description(args)
130 .color(0x5865F2)
131 .build();
132
133 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
134 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
135 }
136
137 "edit" => {
138 if args.is_empty() { return; }
139 let _ = ctx.http.edit_message(channel_id, &msg.id, args).await;
140 }
141
142 "help" => {
143 let help_text = "**Selfbot Commands**\n\
144 `sb!ping` - Check latency\n\
145 `sb!8ball <question>` - Ask the magic 8ball\n\
146 `sb!flip` - Flip a coin\n\
147 `sb!roll [sides]` - Roll a die (default 6)\n\
148 `sb!purge [count]` - Delete your recent messages\n\
149 `sb!embed <text>` - Send an embed\n\
150 `sb!edit <text>` - Edit your message\n\
151 `sb!help` - Show this message";
152 let _ = ctx.http.edit_message(channel_id, &msg.id, help_text).await;
153 }
154
155 _ => {}
156 }
157 }More examples
examples/bot.rs (line 98)
27 async fn on_message(&self, ctx: Context, msg: Message) {
28 let user_cached = ctx.cache.user(&msg.author.id).await.is_some();
29 let ch_cached = ctx.cache.channel(msg.channel_id.as_deref().unwrap_or("")).await.is_some();
30 let content_preview = msg.content.as_deref().unwrap_or("").chars().take(60).collect::<String>();
31 let attachments = msg.attachments.as_ref().map(|a| a.len()).unwrap_or(0);
32 let embeds = msg.embeds.as_ref().map(|e| e.len()).unwrap_or(0);
33 println!(
34 "[msg] author={}#{} channel={} guild={} | \"{}\" | attach={} embeds={} | cache: user={} ch={}",
35 msg.author.username,
36 msg.author.discriminator.as_deref().unwrap_or("0"),
37 msg.channel_id.as_deref().unwrap_or("?"),
38 msg.guild_id.as_deref().unwrap_or("DM"),
39 content_preview,
40 attachments,
41 embeds,
42 user_cached,
43 ch_cached,
44 );
45
46 if msg.author.bot.unwrap_or(false) {
47 return;
48 }
49
50 let content = match msg.content.as_deref() {
51 Some(c) => c,
52 None => return,
53 };
54
55 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
56
57 let (cmd, args) = match parse_command(content) {
58 Some(v) => v,
59 None => return,
60 };
61
62 match cmd {
63 "ping" => {
64 let start = Instant::now();
65 let sent = ctx.http.send_message(channel_id, "Pong!").await;
66 let elapsed = start.elapsed().as_millis();
67
68 if let Ok(sent) = sent {
69 let _ = ctx.http.edit_message(
70 channel_id,
71 &sent.id,
72 &format!("Pong! {}ms", elapsed),
73 ).await;
74 }
75 }
76
77 "say" => {
78 if args.is_empty() {
79 let _ = ctx.http.send_message(channel_id, "Say what?").await;
80 return;
81 }
82 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
83 let _ = ctx.http.send_message(channel_id, args).await;
84 }
85
86 "embed" => {
87 let (title, desc) = match args.split_once('|') {
88 Some((t, d)) => (t.trim(), d.trim()),
89 None => {
90 let _ = ctx.http.send_message(channel_id, "`!embed title | description`").await;
91 return;
92 }
93 };
94
95 let embed = EmbedBuilder::new()
96 .title(title)
97 .description(desc)
98 .color(0x5865F2)
99 .build();
100
101 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
102 }
103
104 "react" => {
105 let _ = ctx.http.add_reaction(channel_id, &msg.id, "❤️").await;
106 }
107
108 "purge" => {
109 let count: u8 = args.parse().unwrap_or(0);
110 if count == 0 || count > 100 {
111 let _ = ctx.http.send_message(channel_id, "1-100.").await;
112 return;
113 }
114
115 let query = GetMessagesQuery {
116 limit: Some(count),
117 ..Default::default()
118 };
119
120 if let Ok(messages) = ctx.http.get_messages(channel_id, query).await {
121 let ids: Vec<&str> = messages.iter().map(|m| m.id.as_str()).collect();
122 let _ = ctx.http.bulk_delete_messages(channel_id, ids).await;
123 }
124 }
125
126 "serverinfo" => {
127 let guild_id = match &msg.guild_id {
128 Some(id) => id.as_str(),
129 None => return,
130 };
131
132 if let Ok(guild) = ctx.http.get_guild(guild_id).await {
133 let name = guild.name.as_deref().unwrap_or("Unknown");
134
135 let members = ctx.http.get_guild_members(guild_id, Some(1000), None).await
136 .map(|m| m.len().to_string())
137 .unwrap_or("?".into());
138
139 let embed = EmbedBuilder::new()
140 .title(name)
141 .field("Members", &members, true)
142 .color(0x5865F2)
143 .build();
144
145 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
146 }
147 }
148
149 "attach" => {
150 if args.is_empty() {
151 let _ = ctx.http.send_message(channel_id, "Usage: `!attach <file path>`").await;
152 return;
153 }
154 let path = std::path::Path::new(args);
155 let filename = path
156 .file_name()
157 .and_then(|n| n.to_str())
158 .unwrap_or("file")
159 .to_string();
160 let content_type = match path.extension().and_then(|e| e.to_str()) {
161 Some("mp3") => "audio/mpeg",
162 Some("mp4") => "video/mp4",
163 Some("mov") => "video/quicktime",
164 Some("webm") => "video/webm",
165 Some("png") => "image/png",
166 Some("jpg") | Some("jpeg") => "image/jpeg",
167 Some("gif") => "image/gif",
168 Some("webp") => "image/webp",
169 Some("txt") => "text/plain",
170 Some("pdf") => "application/pdf",
171 _ => "application/octet-stream",
172 };
173 match tokio::fs::read(path).await {
174 Ok(data) => {
175 let file = AttachmentFile {
176 filename,
177 data,
178 content_type: Some(content_type.to_string()),
179 };
180 match ctx.http.send_files(channel_id, vec![file], None).await {
181 Ok(msg) => println!("[attach] sent message {}", msg.id),
182 Err(e) => eprintln!("[attach] error: {}", e),
183 }
184 }
185 Err(e) => {
186 eprintln!("[attach] failed to read file: {}", e);
187 let _ = ctx.http.send_message(channel_id, &format!("Failed to read file: {}", e)).await;
188 }
189 }
190 }
191
192 "addrole" => {
193 let guild_id = match &msg.guild_id {
194 Some(id) => id.as_str(),
195 None => return,
196 };
197 let parts: Vec<&str> = args.split_whitespace().collect();
198 if parts.len() != 2 {
199 let _ = ctx.http.send_message(channel_id, "Usage: `!addrole <user_id> <role_id>`").await;
200 return;
201 }
202 match ctx.http.add_member_role(guild_id, parts[0], parts[1]).await {
203 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role added").await; }
204 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
205 }
206 }
207
208 "removerole" => {
209 let guild_id = match &msg.guild_id {
210 Some(id) => id.as_str(),
211 None => return,
212 };
213 let parts: Vec<&str> = args.split_whitespace().collect();
214 if parts.len() != 2 {
215 let _ = ctx.http.send_message(channel_id, "Usage: `!removerole <user_id> <role_id>`").await;
216 return;
217 }
218 match ctx.http.remove_member_role(guild_id, parts[0], parts[1]).await {
219 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role removed").await; }
220 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
221 }
222 }
223
224 _ => {}
225 }
226 }pub fn timestamp(self, ts: impl Into<String>) -> Self
pub fn image(self, url: impl Into<String>) -> Self
pub fn thumbnail(self, url: impl Into<String>) -> Self
Sourcepub fn field(
self,
name: impl Into<String>,
value: impl Into<String>,
inline: bool,
) -> Self
pub fn field( self, name: impl Into<String>, value: impl Into<String>, inline: bool, ) -> Self
Examples found in repository?
examples/bot.rs (line 141)
27 async fn on_message(&self, ctx: Context, msg: Message) {
28 let user_cached = ctx.cache.user(&msg.author.id).await.is_some();
29 let ch_cached = ctx.cache.channel(msg.channel_id.as_deref().unwrap_or("")).await.is_some();
30 let content_preview = msg.content.as_deref().unwrap_or("").chars().take(60).collect::<String>();
31 let attachments = msg.attachments.as_ref().map(|a| a.len()).unwrap_or(0);
32 let embeds = msg.embeds.as_ref().map(|e| e.len()).unwrap_or(0);
33 println!(
34 "[msg] author={}#{} channel={} guild={} | \"{}\" | attach={} embeds={} | cache: user={} ch={}",
35 msg.author.username,
36 msg.author.discriminator.as_deref().unwrap_or("0"),
37 msg.channel_id.as_deref().unwrap_or("?"),
38 msg.guild_id.as_deref().unwrap_or("DM"),
39 content_preview,
40 attachments,
41 embeds,
42 user_cached,
43 ch_cached,
44 );
45
46 if msg.author.bot.unwrap_or(false) {
47 return;
48 }
49
50 let content = match msg.content.as_deref() {
51 Some(c) => c,
52 None => return,
53 };
54
55 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
56
57 let (cmd, args) = match parse_command(content) {
58 Some(v) => v,
59 None => return,
60 };
61
62 match cmd {
63 "ping" => {
64 let start = Instant::now();
65 let sent = ctx.http.send_message(channel_id, "Pong!").await;
66 let elapsed = start.elapsed().as_millis();
67
68 if let Ok(sent) = sent {
69 let _ = ctx.http.edit_message(
70 channel_id,
71 &sent.id,
72 &format!("Pong! {}ms", elapsed),
73 ).await;
74 }
75 }
76
77 "say" => {
78 if args.is_empty() {
79 let _ = ctx.http.send_message(channel_id, "Say what?").await;
80 return;
81 }
82 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
83 let _ = ctx.http.send_message(channel_id, args).await;
84 }
85
86 "embed" => {
87 let (title, desc) = match args.split_once('|') {
88 Some((t, d)) => (t.trim(), d.trim()),
89 None => {
90 let _ = ctx.http.send_message(channel_id, "`!embed title | description`").await;
91 return;
92 }
93 };
94
95 let embed = EmbedBuilder::new()
96 .title(title)
97 .description(desc)
98 .color(0x5865F2)
99 .build();
100
101 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
102 }
103
104 "react" => {
105 let _ = ctx.http.add_reaction(channel_id, &msg.id, "❤️").await;
106 }
107
108 "purge" => {
109 let count: u8 = args.parse().unwrap_or(0);
110 if count == 0 || count > 100 {
111 let _ = ctx.http.send_message(channel_id, "1-100.").await;
112 return;
113 }
114
115 let query = GetMessagesQuery {
116 limit: Some(count),
117 ..Default::default()
118 };
119
120 if let Ok(messages) = ctx.http.get_messages(channel_id, query).await {
121 let ids: Vec<&str> = messages.iter().map(|m| m.id.as_str()).collect();
122 let _ = ctx.http.bulk_delete_messages(channel_id, ids).await;
123 }
124 }
125
126 "serverinfo" => {
127 let guild_id = match &msg.guild_id {
128 Some(id) => id.as_str(),
129 None => return,
130 };
131
132 if let Ok(guild) = ctx.http.get_guild(guild_id).await {
133 let name = guild.name.as_deref().unwrap_or("Unknown");
134
135 let members = ctx.http.get_guild_members(guild_id, Some(1000), None).await
136 .map(|m| m.len().to_string())
137 .unwrap_or("?".into());
138
139 let embed = EmbedBuilder::new()
140 .title(name)
141 .field("Members", &members, true)
142 .color(0x5865F2)
143 .build();
144
145 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
146 }
147 }
148
149 "attach" => {
150 if args.is_empty() {
151 let _ = ctx.http.send_message(channel_id, "Usage: `!attach <file path>`").await;
152 return;
153 }
154 let path = std::path::Path::new(args);
155 let filename = path
156 .file_name()
157 .and_then(|n| n.to_str())
158 .unwrap_or("file")
159 .to_string();
160 let content_type = match path.extension().and_then(|e| e.to_str()) {
161 Some("mp3") => "audio/mpeg",
162 Some("mp4") => "video/mp4",
163 Some("mov") => "video/quicktime",
164 Some("webm") => "video/webm",
165 Some("png") => "image/png",
166 Some("jpg") | Some("jpeg") => "image/jpeg",
167 Some("gif") => "image/gif",
168 Some("webp") => "image/webp",
169 Some("txt") => "text/plain",
170 Some("pdf") => "application/pdf",
171 _ => "application/octet-stream",
172 };
173 match tokio::fs::read(path).await {
174 Ok(data) => {
175 let file = AttachmentFile {
176 filename,
177 data,
178 content_type: Some(content_type.to_string()),
179 };
180 match ctx.http.send_files(channel_id, vec![file], None).await {
181 Ok(msg) => println!("[attach] sent message {}", msg.id),
182 Err(e) => eprintln!("[attach] error: {}", e),
183 }
184 }
185 Err(e) => {
186 eprintln!("[attach] failed to read file: {}", e);
187 let _ = ctx.http.send_message(channel_id, &format!("Failed to read file: {}", e)).await;
188 }
189 }
190 }
191
192 "addrole" => {
193 let guild_id = match &msg.guild_id {
194 Some(id) => id.as_str(),
195 None => return,
196 };
197 let parts: Vec<&str> = args.split_whitespace().collect();
198 if parts.len() != 2 {
199 let _ = ctx.http.send_message(channel_id, "Usage: `!addrole <user_id> <role_id>`").await;
200 return;
201 }
202 match ctx.http.add_member_role(guild_id, parts[0], parts[1]).await {
203 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role added").await; }
204 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
205 }
206 }
207
208 "removerole" => {
209 let guild_id = match &msg.guild_id {
210 Some(id) => id.as_str(),
211 None => return,
212 };
213 let parts: Vec<&str> = args.split_whitespace().collect();
214 if parts.len() != 2 {
215 let _ = ctx.http.send_message(channel_id, "Usage: `!removerole <user_id> <role_id>`").await;
216 return;
217 }
218 match ctx.http.remove_member_role(guild_id, parts[0], parts[1]).await {
219 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role removed").await; }
220 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
221 }
222 }
223
224 _ => {}
225 }
226 }Sourcepub fn build(self) -> Embed
pub fn build(self) -> Embed
Examples found in repository?
examples/selfbot.rs (line 131)
28 async fn on_message(&self, ctx: Context, msg: Message) {
29 if !is_me(&ctx, &msg).await {
30 return;
31 }
32
33 let content = match msg.content.as_deref() {
34 Some(c) => c,
35 None => return,
36 };
37
38 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
39
40 let (cmd, args) = match parse_command(content) {
41 Some(v) => v,
42 None => return,
43 };
44
45 match cmd {
46 "ping" => {
47 let start = Instant::now();
48 let sent = ctx.http.send_message(channel_id, "Pong!").await;
49 let elapsed = start.elapsed().as_millis();
50 if let Ok(sent) = sent {
51 let _ = ctx.http.edit_message(
52 channel_id,
53 &sent.id,
54 &format!("Pong! `{}ms`", elapsed),
55 ).await;
56 }
57 }
58
59 "8ball" => {
60 if args.is_empty() {
61 let _ = ctx.http.edit_message(channel_id, &msg.id, "Ask a question!").await;
62 return;
63 }
64 let responses = [
65 "Yes", "No", "Maybe", "Definitely", "Absolutely not",
66 "Ask again later", "Better not tell you now", "Cannot predict now",
67 "Don't count on it", "It is certain", "Most likely", "Outlook good",
68 "Reply hazy, try again", "Signs point to yes", "Very doubtful", "Without a doubt",
69 ];
70 let idx = (std::time::SystemTime::now()
71 .duration_since(std::time::UNIX_EPOCH)
72 .unwrap()
73 .as_nanos() % responses.len() as u128) as usize;
74 let answer = responses[idx];
75 let _ = ctx.http.edit_message(channel_id, &msg.id, answer).await;
76 }
77
78 "flip" => {
79 let result = if std::time::SystemTime::now()
80 .duration_since(std::time::UNIX_EPOCH)
81 .unwrap()
82 .as_nanos().is_multiple_of(2) { "Heads" } else { "Tails" };
83 let _ = ctx.http.edit_message(channel_id, &msg.id, result).await;
84 }
85
86 "roll" => {
87 let sides: u32 = args.parse().unwrap_or(6);
88 if !(2..=100).contains(&sides) {
89 let _ = ctx.http.edit_message(channel_id, &msg.id, "Use 2-100 sides").await;
90 return;
91 }
92 let result = (std::time::SystemTime::now()
93 .duration_since(std::time::UNIX_EPOCH)
94 .unwrap()
95 .as_nanos() % sides as u128) as u32 + 1;
96 let _ = ctx.http.edit_message(channel_id, &msg.id, &format!("Rolled {}/{}", result, sides)).await;
97 }
98
99 "purge" => {
100 let count: u8 = args.parse().unwrap_or(10).min(100);
101 let query = GetMessagesQuery {
102 limit: Some(count),
103 before: None,
104 after: None,
105 around: None,
106 };
107 match ctx.http.get_messages(channel_id, query).await {
108 Ok(messages) => {
109 let my_id = ctx.cache.current_user().await.map(|u| u.id).unwrap_or_default();
110 let my_messages: Vec<_> = messages.iter()
111 .filter(|m| m.author.id == my_id)
112 .map(|m| m.id.as_str())
113 .collect();
114
115 if !my_messages.is_empty() {
116 let _ = ctx.http.bulk_delete_messages(channel_id, my_messages).await;
117 }
118 }
119 Err(e) => eprintln!("[purge] failed: {}", e),
120 }
121 }
122
123 "embed" => {
124 if args.is_empty() {
125 let _ = ctx.http.edit_message(channel_id, &msg.id, "Usage: sb!embed <text>").await;
126 return;
127 }
128 let embed = EmbedBuilder::new()
129 .description(args)
130 .color(0x5865F2)
131 .build();
132
133 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
134 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
135 }
136
137 "edit" => {
138 if args.is_empty() { return; }
139 let _ = ctx.http.edit_message(channel_id, &msg.id, args).await;
140 }
141
142 "help" => {
143 let help_text = "**Selfbot Commands**\n\
144 `sb!ping` - Check latency\n\
145 `sb!8ball <question>` - Ask the magic 8ball\n\
146 `sb!flip` - Flip a coin\n\
147 `sb!roll [sides]` - Roll a die (default 6)\n\
148 `sb!purge [count]` - Delete your recent messages\n\
149 `sb!embed <text>` - Send an embed\n\
150 `sb!edit <text>` - Edit your message\n\
151 `sb!help` - Show this message";
152 let _ = ctx.http.edit_message(channel_id, &msg.id, help_text).await;
153 }
154
155 _ => {}
156 }
157 }More examples
examples/bot.rs (line 99)
27 async fn on_message(&self, ctx: Context, msg: Message) {
28 let user_cached = ctx.cache.user(&msg.author.id).await.is_some();
29 let ch_cached = ctx.cache.channel(msg.channel_id.as_deref().unwrap_or("")).await.is_some();
30 let content_preview = msg.content.as_deref().unwrap_or("").chars().take(60).collect::<String>();
31 let attachments = msg.attachments.as_ref().map(|a| a.len()).unwrap_or(0);
32 let embeds = msg.embeds.as_ref().map(|e| e.len()).unwrap_or(0);
33 println!(
34 "[msg] author={}#{} channel={} guild={} | \"{}\" | attach={} embeds={} | cache: user={} ch={}",
35 msg.author.username,
36 msg.author.discriminator.as_deref().unwrap_or("0"),
37 msg.channel_id.as_deref().unwrap_or("?"),
38 msg.guild_id.as_deref().unwrap_or("DM"),
39 content_preview,
40 attachments,
41 embeds,
42 user_cached,
43 ch_cached,
44 );
45
46 if msg.author.bot.unwrap_or(false) {
47 return;
48 }
49
50 let content = match msg.content.as_deref() {
51 Some(c) => c,
52 None => return,
53 };
54
55 let channel_id = msg.channel_id.as_deref().unwrap_or_default();
56
57 let (cmd, args) = match parse_command(content) {
58 Some(v) => v,
59 None => return,
60 };
61
62 match cmd {
63 "ping" => {
64 let start = Instant::now();
65 let sent = ctx.http.send_message(channel_id, "Pong!").await;
66 let elapsed = start.elapsed().as_millis();
67
68 if let Ok(sent) = sent {
69 let _ = ctx.http.edit_message(
70 channel_id,
71 &sent.id,
72 &format!("Pong! {}ms", elapsed),
73 ).await;
74 }
75 }
76
77 "say" => {
78 if args.is_empty() {
79 let _ = ctx.http.send_message(channel_id, "Say what?").await;
80 return;
81 }
82 let _ = ctx.http.delete_message(channel_id, &msg.id).await;
83 let _ = ctx.http.send_message(channel_id, args).await;
84 }
85
86 "embed" => {
87 let (title, desc) = match args.split_once('|') {
88 Some((t, d)) => (t.trim(), d.trim()),
89 None => {
90 let _ = ctx.http.send_message(channel_id, "`!embed title | description`").await;
91 return;
92 }
93 };
94
95 let embed = EmbedBuilder::new()
96 .title(title)
97 .description(desc)
98 .color(0x5865F2)
99 .build();
100
101 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
102 }
103
104 "react" => {
105 let _ = ctx.http.add_reaction(channel_id, &msg.id, "❤️").await;
106 }
107
108 "purge" => {
109 let count: u8 = args.parse().unwrap_or(0);
110 if count == 0 || count > 100 {
111 let _ = ctx.http.send_message(channel_id, "1-100.").await;
112 return;
113 }
114
115 let query = GetMessagesQuery {
116 limit: Some(count),
117 ..Default::default()
118 };
119
120 if let Ok(messages) = ctx.http.get_messages(channel_id, query).await {
121 let ids: Vec<&str> = messages.iter().map(|m| m.id.as_str()).collect();
122 let _ = ctx.http.bulk_delete_messages(channel_id, ids).await;
123 }
124 }
125
126 "serverinfo" => {
127 let guild_id = match &msg.guild_id {
128 Some(id) => id.as_str(),
129 None => return,
130 };
131
132 if let Ok(guild) = ctx.http.get_guild(guild_id).await {
133 let name = guild.name.as_deref().unwrap_or("Unknown");
134
135 let members = ctx.http.get_guild_members(guild_id, Some(1000), None).await
136 .map(|m| m.len().to_string())
137 .unwrap_or("?".into());
138
139 let embed = EmbedBuilder::new()
140 .title(name)
141 .field("Members", &members, true)
142 .color(0x5865F2)
143 .build();
144
145 let _ = ctx.http.send_embed(channel_id, None, vec![embed]).await;
146 }
147 }
148
149 "attach" => {
150 if args.is_empty() {
151 let _ = ctx.http.send_message(channel_id, "Usage: `!attach <file path>`").await;
152 return;
153 }
154 let path = std::path::Path::new(args);
155 let filename = path
156 .file_name()
157 .and_then(|n| n.to_str())
158 .unwrap_or("file")
159 .to_string();
160 let content_type = match path.extension().and_then(|e| e.to_str()) {
161 Some("mp3") => "audio/mpeg",
162 Some("mp4") => "video/mp4",
163 Some("mov") => "video/quicktime",
164 Some("webm") => "video/webm",
165 Some("png") => "image/png",
166 Some("jpg") | Some("jpeg") => "image/jpeg",
167 Some("gif") => "image/gif",
168 Some("webp") => "image/webp",
169 Some("txt") => "text/plain",
170 Some("pdf") => "application/pdf",
171 _ => "application/octet-stream",
172 };
173 match tokio::fs::read(path).await {
174 Ok(data) => {
175 let file = AttachmentFile {
176 filename,
177 data,
178 content_type: Some(content_type.to_string()),
179 };
180 match ctx.http.send_files(channel_id, vec![file], None).await {
181 Ok(msg) => println!("[attach] sent message {}", msg.id),
182 Err(e) => eprintln!("[attach] error: {}", e),
183 }
184 }
185 Err(e) => {
186 eprintln!("[attach] failed to read file: {}", e);
187 let _ = ctx.http.send_message(channel_id, &format!("Failed to read file: {}", e)).await;
188 }
189 }
190 }
191
192 "addrole" => {
193 let guild_id = match &msg.guild_id {
194 Some(id) => id.as_str(),
195 None => return,
196 };
197 let parts: Vec<&str> = args.split_whitespace().collect();
198 if parts.len() != 2 {
199 let _ = ctx.http.send_message(channel_id, "Usage: `!addrole <user_id> <role_id>`").await;
200 return;
201 }
202 match ctx.http.add_member_role(guild_id, parts[0], parts[1]).await {
203 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role added").await; }
204 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
205 }
206 }
207
208 "removerole" => {
209 let guild_id = match &msg.guild_id {
210 Some(id) => id.as_str(),
211 None => return,
212 };
213 let parts: Vec<&str> = args.split_whitespace().collect();
214 if parts.len() != 2 {
215 let _ = ctx.http.send_message(channel_id, "Usage: `!removerole <user_id> <role_id>`").await;
216 return;
217 }
218 match ctx.http.remove_member_role(guild_id, parts[0], parts[1]).await {
219 Ok(_) => { let _ = ctx.http.send_message(channel_id, "Role removed").await; }
220 Err(e) => { let _ = ctx.http.send_message(channel_id, &format!("Error: {}", e)).await; }
221 }
222 }
223
224 _ => {}
225 }
226 }Trait Implementations§
Source§impl Debug for EmbedBuilder
impl Debug for EmbedBuilder
Source§impl Default for EmbedBuilder
impl Default for EmbedBuilder
Source§fn default() -> EmbedBuilder
fn default() -> EmbedBuilder
Returns the “default value” for a type. Read more
Auto Trait Implementations§
impl Freeze for EmbedBuilder
impl RefUnwindSafe for EmbedBuilder
impl Send for EmbedBuilder
impl Sync for EmbedBuilder
impl Unpin for EmbedBuilder
impl UnsafeUnpin for EmbedBuilder
impl UnwindSafe for EmbedBuilder
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