Skip to main content

Packet

Struct Packet 

Source
pub struct Packet {
    pub opcode: Opcode,
    pub payload: Value,
}
Expand description

Represents a Discord IPC message packet.

Fields§

§opcode: Opcode§payload: Value

Implementations§

Source§

impl Packet

Source

pub fn new(opcode: Opcode, payload: impl Into<Value>) -> Self

Creates a new packet with the given opcode and payload.

§Arguments
  • opcode: The Opcode for the packet.
  • payload: Data that can be converted into a JSON Value.
Examples found in repository?
examples/01_basics.rs (line 39)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8    // === Build a client ===
9
10    // Build your client instance (with your own application ID)
11    // You can create one in https://discord.com/developers/applications
12    let client = Client::new("<application_id>");
13
14    // Listen to "READY" event
15    // The "READY" event is triggered when the client has successfully connected to Discord
16    // and is ready to receive and send packets.
17    client.on("READY", |client, _packet| {
18        println!("Connected");
19        // You will receive as arguments a reference to the client instance you created and the incoming Discord packet.
20        // Once the client is connected, you can start interacting with Discord's IPC.
21
22        // === Build a packet ===
23        // A packet is built from an opcode and a payload.
24        // The opcode establishes the kind of operation to be performed
25        // The most common opcodes are Opcode::Frame (1) and Opcode::Ping (3).
26        // Frame is used for most operations, while Ping is only used to ping Discord.
27        let opcode = Opcode::Ping;
28        // The payload contains the command data in JSON format in addition to a
29        // unique nonce for identifying the packet exchange.
30        // The payload of a ping packet is optional; you can send an empty value if you prefer.
31        // You can listen to the opcode (4)Pong to handle the response
32        // or you can include a "nonce" field in the payload.
33        let nonce = Packet::generate_nonce();
34        let payload = json!({
35            "nonce": nonce,
36            "example_field": "ping"
37        });
38
39        let ping = Packet::new(opcode, payload);
40
41        // === Listen for a response ===
42        client.once(nonce, |_client, packet| {
43            // If you receive this, the ping was successful.
44            println!("Pong!");
45            // The received packet has the opcode (4)Pong and has the same payload as the one sent before.
46            println!("{}", packet);
47        });
48
49        // === Send the packet ===
50        // Once you set up the listener, you can now send your packet
51        if let Err(e) = client.send(ping) {
52            eprintln!("Couldn't send packet: {}", e)
53        };
54        // When a response is received, the listener will be triggered.
55    });
56
57    // Try to connect
58    client.connect()?;
59    std::io::stdin().read_line(&mut String::new()).unwrap();
60    client.disconnect()?;
61    println!("Disconnected");
62
63    Ok(())
64}
Source

pub fn new_activity(activity: Option<&Activity>, nonce: Option<&str>) -> Self

Creates a new activity packet for Discord IPC.

§Arguments
  • activity: Optional Activity. Pass None to clear.
  • nonce: Optional nonce string.
Examples found in repository?
examples/00_simple.rs (line 32)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8    // Build your client instance (with your own application ID)
9    // You can create one in https://discord.com/developers/applications
10    let client = Client::new_simple("<application_id>");
11
12    // `connect_and_wait()` is a blocking method that sends a connection request,
13    // waits for a direct response, and returns the response packet.
14    let connection_response = client.connect_and_wait()?;
15
16    // You can use `filter()` in any packet to search for an error response.
17    match connection_response.filter() {
18        Ok(_packet) => println!("Connected"),
19        Err(e) => {
20            eprintln!("Couldn't connect to Discord: {}", e);
21            return Ok(());
22        }
23    }
24
25    // === Set an activity ===
26    let activity = Activity::new().details("Simple activity");
27
28    // Build an activity packet.
29    // Pass Some(&activity) to set an activity or None to clear it.
30    // The second argument is a nonce used to identify a packet exchange, but it's not needed here,
31    // since `send_and_wait()` already waits for a direct response.
32    let packet = Packet::new_activity(Some(&activity), None);
33
34    // You can use `filter()` in `send_and_wait()` as it returns a packet
35    match client.send_and_wait(packet)?.filter() {
36        Ok(_packet) => println!("Activity has been set!"),
37        Err(e) => eprintln!("Couldn't set activity: {}", e),
38    };
39
40    std::thread::sleep(std::time::Duration::from_secs(10));
41
42    // === Clear the activity ===
43    let packet = Packet::new_activity(None, None);
44    match client.send_and_wait(packet)?.filter() {
45        Ok(_packet) => println!("Activity has been cleared!"),
46        Err(e) => eprintln!("Couldn't clear activity: {}", e),
47    };
48
49    std::thread::sleep(std::time::Duration::from_secs(3));
50    client.disconnect()?;
51    println!("Disconnected");
52
53    Ok(())
54}
More examples
Hide additional examples
examples/02_activity.rs (line 40)
7fn main() -> Result<()> {
8    let client = Client::new("<application_id>");
9
10    client.on("READY", |client, _packet| {
11        println!("Connected");
12
13        // === Create an activity ===
14
15        // You can create activities this way... (recommended)
16        let activity = Activity::new()
17            .details("In Workspace: test")
18            .state("Dealing with proc-macros")
19            .timestamps(Timestamps::new().start_now())
20            .button(Button::new("Get started!", "https://rustup.rs/"));
21
22        // Or this way...
23        let _activity = Activity {
24            details: Some("In Workspace: test".to_string()),
25            state: Some("Dealing with proc-macros".to_string()),
26            timestamps: Some(Timestamps::new().start_now()),
27            buttons: Some(vec![Button {
28                label: "Get started!".to_string(),
29                url: "https://rustup.rs/".to_string(),
30            }]),
31            ..Activity::default()
32        };
33        // Note that this method is more susceptible to errors as it skips structural checks.
34
35        // === Build the packet ===
36        let nonce = Packet::generate_nonce(); // Unique nonce for identifying the packet exchange
37
38        // You can manually build the activity packet with Packet::new()
39        // or you can use Packet::new_activity()
40        let activity_packet = Packet::new_activity(Some(&activity), Some(&nonce));
41
42        // === Listen for a response ===
43        client.once(nonce, |client, packet| {
44            // Setting up an activity is an operation that could fail,
45            // so the packet payload may contain a success or an error.
46            // You can use packet.filter() to automatically search for errors in its payload.
47            match packet.filter() {
48                Ok(_packet) => {
49                    println!("Activity has been set!");
50
51                    std::thread::sleep(std::time::Duration::from_secs(10));
52
53                    if let Err(e) = client.send(Packet::new_activity(None, None)) {
54                        eprintln!("Couldn't send packet: {}", e)
55                    };
56                    println!("Activity cleared!");
57                }
58                Err(e) => println!("Couldn't set activity: {}", e),
59            }
60        });
61
62        // Once you set up the listener, you can now send the activity packet.
63        if let Err(e) = client.send(activity_packet) {
64            eprintln!("Couldn't send packet: {}", e)
65        };
66    });
67
68    // Try to connect
69    client.connect()?;
70    std::io::stdin().read_line(&mut String::new()).unwrap();
71    client.disconnect()?;
72    println!("Disconnected");
73
74    Ok(())
75}
Source

pub fn generate_nonce() -> String

Generates a unique nonce using UUID v4.

Examples found in repository?
examples/01_basics.rs (line 33)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8    // === Build a client ===
9
10    // Build your client instance (with your own application ID)
11    // You can create one in https://discord.com/developers/applications
12    let client = Client::new("<application_id>");
13
14    // Listen to "READY" event
15    // The "READY" event is triggered when the client has successfully connected to Discord
16    // and is ready to receive and send packets.
17    client.on("READY", |client, _packet| {
18        println!("Connected");
19        // You will receive as arguments a reference to the client instance you created and the incoming Discord packet.
20        // Once the client is connected, you can start interacting with Discord's IPC.
21
22        // === Build a packet ===
23        // A packet is built from an opcode and a payload.
24        // The opcode establishes the kind of operation to be performed
25        // The most common opcodes are Opcode::Frame (1) and Opcode::Ping (3).
26        // Frame is used for most operations, while Ping is only used to ping Discord.
27        let opcode = Opcode::Ping;
28        // The payload contains the command data in JSON format in addition to a
29        // unique nonce for identifying the packet exchange.
30        // The payload of a ping packet is optional; you can send an empty value if you prefer.
31        // You can listen to the opcode (4)Pong to handle the response
32        // or you can include a "nonce" field in the payload.
33        let nonce = Packet::generate_nonce();
34        let payload = json!({
35            "nonce": nonce,
36            "example_field": "ping"
37        });
38
39        let ping = Packet::new(opcode, payload);
40
41        // === Listen for a response ===
42        client.once(nonce, |_client, packet| {
43            // If you receive this, the ping was successful.
44            println!("Pong!");
45            // The received packet has the opcode (4)Pong and has the same payload as the one sent before.
46            println!("{}", packet);
47        });
48
49        // === Send the packet ===
50        // Once you set up the listener, you can now send your packet
51        if let Err(e) = client.send(ping) {
52            eprintln!("Couldn't send packet: {}", e)
53        };
54        // When a response is received, the listener will be triggered.
55    });
56
57    // Try to connect
58    client.connect()?;
59    std::io::stdin().read_line(&mut String::new()).unwrap();
60    client.disconnect()?;
61    println!("Disconnected");
62
63    Ok(())
64}
More examples
Hide additional examples
examples/02_activity.rs (line 36)
7fn main() -> Result<()> {
8    let client = Client::new("<application_id>");
9
10    client.on("READY", |client, _packet| {
11        println!("Connected");
12
13        // === Create an activity ===
14
15        // You can create activities this way... (recommended)
16        let activity = Activity::new()
17            .details("In Workspace: test")
18            .state("Dealing with proc-macros")
19            .timestamps(Timestamps::new().start_now())
20            .button(Button::new("Get started!", "https://rustup.rs/"));
21
22        // Or this way...
23        let _activity = Activity {
24            details: Some("In Workspace: test".to_string()),
25            state: Some("Dealing with proc-macros".to_string()),
26            timestamps: Some(Timestamps::new().start_now()),
27            buttons: Some(vec![Button {
28                label: "Get started!".to_string(),
29                url: "https://rustup.rs/".to_string(),
30            }]),
31            ..Activity::default()
32        };
33        // Note that this method is more susceptible to errors as it skips structural checks.
34
35        // === Build the packet ===
36        let nonce = Packet::generate_nonce(); // Unique nonce for identifying the packet exchange
37
38        // You can manually build the activity packet with Packet::new()
39        // or you can use Packet::new_activity()
40        let activity_packet = Packet::new_activity(Some(&activity), Some(&nonce));
41
42        // === Listen for a response ===
43        client.once(nonce, |client, packet| {
44            // Setting up an activity is an operation that could fail,
45            // so the packet payload may contain a success or an error.
46            // You can use packet.filter() to automatically search for errors in its payload.
47            match packet.filter() {
48                Ok(_packet) => {
49                    println!("Activity has been set!");
50
51                    std::thread::sleep(std::time::Duration::from_secs(10));
52
53                    if let Err(e) = client.send(Packet::new_activity(None, None)) {
54                        eprintln!("Couldn't send packet: {}", e)
55                    };
56                    println!("Activity cleared!");
57                }
58                Err(e) => println!("Couldn't set activity: {}", e),
59            }
60        });
61
62        // Once you set up the listener, you can now send the activity packet.
63        if let Err(e) = client.send(activity_packet) {
64            eprintln!("Couldn't send packet: {}", e)
65        };
66    });
67
68    // Try to connect
69    client.connect()?;
70    std::io::stdin().read_line(&mut String::new()).unwrap();
71    client.disconnect()?;
72    println!("Disconnected");
73
74    Ok(())
75}
Source

pub fn decode_header(header: &[u8; 8]) -> Result<(u32, u32)>

Decodes a Discord IPC response header.

§Errors
  • DecodeError: If the header is malformed, incomplete, or cannot be decoded.
Source

pub fn filter(self) -> Result<Packet, BadResponseError>

Checks for errors in a Discord IPC response payload.

§Returns
  • Ok(Packet) if no error is found.
  • Err(BadResponseError) if there is an error.

See BadResponseError

Examples found in repository?
examples/00_simple.rs (line 17)
7fn main() -> Result<(), Box<dyn std::error::Error>> {
8    // Build your client instance (with your own application ID)
9    // You can create one in https://discord.com/developers/applications
10    let client = Client::new_simple("<application_id>");
11
12    // `connect_and_wait()` is a blocking method that sends a connection request,
13    // waits for a direct response, and returns the response packet.
14    let connection_response = client.connect_and_wait()?;
15
16    // You can use `filter()` in any packet to search for an error response.
17    match connection_response.filter() {
18        Ok(_packet) => println!("Connected"),
19        Err(e) => {
20            eprintln!("Couldn't connect to Discord: {}", e);
21            return Ok(());
22        }
23    }
24
25    // === Set an activity ===
26    let activity = Activity::new().details("Simple activity");
27
28    // Build an activity packet.
29    // Pass Some(&activity) to set an activity or None to clear it.
30    // The second argument is a nonce used to identify a packet exchange, but it's not needed here,
31    // since `send_and_wait()` already waits for a direct response.
32    let packet = Packet::new_activity(Some(&activity), None);
33
34    // You can use `filter()` in `send_and_wait()` as it returns a packet
35    match client.send_and_wait(packet)?.filter() {
36        Ok(_packet) => println!("Activity has been set!"),
37        Err(e) => eprintln!("Couldn't set activity: {}", e),
38    };
39
40    std::thread::sleep(std::time::Duration::from_secs(10));
41
42    // === Clear the activity ===
43    let packet = Packet::new_activity(None, None);
44    match client.send_and_wait(packet)?.filter() {
45        Ok(_packet) => println!("Activity has been cleared!"),
46        Err(e) => eprintln!("Couldn't clear activity: {}", e),
47    };
48
49    std::thread::sleep(std::time::Duration::from_secs(3));
50    client.disconnect()?;
51    println!("Disconnected");
52
53    Ok(())
54}
More examples
Hide additional examples
examples/02_activity.rs (line 47)
7fn main() -> Result<()> {
8    let client = Client::new("<application_id>");
9
10    client.on("READY", |client, _packet| {
11        println!("Connected");
12
13        // === Create an activity ===
14
15        // You can create activities this way... (recommended)
16        let activity = Activity::new()
17            .details("In Workspace: test")
18            .state("Dealing with proc-macros")
19            .timestamps(Timestamps::new().start_now())
20            .button(Button::new("Get started!", "https://rustup.rs/"));
21
22        // Or this way...
23        let _activity = Activity {
24            details: Some("In Workspace: test".to_string()),
25            state: Some("Dealing with proc-macros".to_string()),
26            timestamps: Some(Timestamps::new().start_now()),
27            buttons: Some(vec![Button {
28                label: "Get started!".to_string(),
29                url: "https://rustup.rs/".to_string(),
30            }]),
31            ..Activity::default()
32        };
33        // Note that this method is more susceptible to errors as it skips structural checks.
34
35        // === Build the packet ===
36        let nonce = Packet::generate_nonce(); // Unique nonce for identifying the packet exchange
37
38        // You can manually build the activity packet with Packet::new()
39        // or you can use Packet::new_activity()
40        let activity_packet = Packet::new_activity(Some(&activity), Some(&nonce));
41
42        // === Listen for a response ===
43        client.once(nonce, |client, packet| {
44            // Setting up an activity is an operation that could fail,
45            // so the packet payload may contain a success or an error.
46            // You can use packet.filter() to automatically search for errors in its payload.
47            match packet.filter() {
48                Ok(_packet) => {
49                    println!("Activity has been set!");
50
51                    std::thread::sleep(std::time::Duration::from_secs(10));
52
53                    if let Err(e) = client.send(Packet::new_activity(None, None)) {
54                        eprintln!("Couldn't send packet: {}", e)
55                    };
56                    println!("Activity cleared!");
57                }
58                Err(e) => println!("Couldn't set activity: {}", e),
59            }
60        });
61
62        // Once you set up the listener, you can now send the activity packet.
63        if let Err(e) = client.send(activity_packet) {
64            eprintln!("Couldn't send packet: {}", e)
65        };
66    });
67
68    // Try to connect
69    client.connect()?;
70    std::io::stdin().read_line(&mut String::new()).unwrap();
71    client.disconnect()?;
72    println!("Disconnected");
73
74    Ok(())
75}

Trait Implementations§

Source§

impl Clone for Packet

Source§

fn clone(&self) -> Packet

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Packet

Source§

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

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

impl Display for Packet

Source§

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

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

impl Serialize for Packet

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. 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<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
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.