Skip to main content

EmbedBuilder

Struct EmbedBuilder 

Source
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

Source

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
Hide additional 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    }
Source

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    }
Source

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
Hide additional 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    }
Source

pub fn url(self, url: impl Into<String>) -> Self

Source

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
Hide additional 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    }
Source

pub fn timestamp(self, ts: impl Into<String>) -> Self

Source

pub fn footer(self, text: impl Into<String>, icon_url: Option<String>) -> Self

Source

pub fn image(self, url: impl Into<String>) -> Self

Source

pub fn thumbnail(self, url: impl Into<String>) -> Self

Source

pub fn author( self, name: impl Into<String>, url: Option<String>, icon_url: Option<String>, ) -> Self

Source

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    }
Source

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
Hide additional 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

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for EmbedBuilder

Source§

fn default() -> EmbedBuilder

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more