Skip to main content

kdeconnect_proto/packet/
runcommand.rs

1//! The RunCommand plugin allows defining and executing remote commands.
2
3use hashbrown::HashMap;
4use serde::{Deserialize, Serialize};
5
6#[cfg(not(feature = "std"))]
7use alloc::string::String;
8
9use crate::packet::{NetworkPacket, NetworkPacketBody};
10
11/// A value of the map in the list of commands of the [`RunCommandPacket::command_list`] field.
12#[derive(Serialize, Deserialize, Debug, Clone)]
13pub struct RunCommandValue {
14    /// A displayed name for the command.
15    pub name: String,
16
17    /// The command to execute.
18    pub command: String,
19}
20
21/// This packet is a list of available commands.
22///
23/// <https://invent.kde.org/network/kdeconnect-meta/blob/master/protocol.md#kdeconnectruncommand>
24#[derive(Serialize, Deserialize, Debug, Clone)]
25#[serde(rename_all = "camelCase")]
26pub struct RunCommandPacket {
27    /// A JSON-serialized dictionary of commands that the device offers. The key is sent in a
28    /// kdeconnect.runcommand.request packet to execute its corresponding command. Each value has
29    /// a name field and a command field, e.g
30    /// `{ "command-id1": { "name": "Command", "command": "/path/to/command1" } }`.
31    pub command_list: String,
32}
33
34/// This packet is a runcommand status update.
35///
36/// <https://invent.kde.org/network/kdeconnect-meta/blob/master/protocol.md#kdeconnectruncommandrequest>
37#[derive(Serialize, Deserialize, Debug, Clone)]
38#[serde(rename_all = "camelCase")]
39pub struct RunCommandRequestPacket {
40    /// If the packet body contains this field it is a request to execute the command with the ID key.
41    #[serde(skip_serializing_if = "Option::is_none")]
42    #[serde(default)]
43    pub key: Option<String>,
44
45    /// If the packet body contains this field it is a request for the command list.
46    #[serde(skip_serializing_if = "Option::is_none")]
47    #[serde(default)]
48    pub request_command_list: Option<bool>,
49}
50
51impl NetworkPacket {
52    /// Make a [`NetworkPacket`] with a [`RunCommandPacket`] payload listing all available commands.
53    pub fn run_command_list_response(command_list: &HashMap<String, RunCommandValue>) -> Self {
54        NetworkPacket::new(NetworkPacketBody::RunCommand(RunCommandPacket {
55            command_list: serde_json::to_string(command_list).expect("malformed command list JSON"),
56        }))
57    }
58
59    /// Make a [`NetworkPacket`] with a [`RunCommandRequestPacket`] payload ready to request the
60    /// list of commands.
61    pub fn run_command_request_list() -> Self {
62        NetworkPacket::new(NetworkPacketBody::RunCommandRequest(RunCommandRequestPacket {
63            key: None,
64            request_command_list: Some(true),
65        }))
66    }
67
68    /// Make a [`NetworkPacket`] with a [`RunCommandRequestPacket`] payload asking to execute the
69    /// provided command.
70    pub fn run_command_exec<T: Into<String>>(key: T) -> Self {
71        NetworkPacket::new(NetworkPacketBody::RunCommandRequest(RunCommandRequestPacket {
72            key: Some(key.into()),
73            request_command_list: None,
74        }))
75    }
76}