obby_client/command.rs
1//! What a host asks the connection to do.
2//!
3//! One enum rather than a method per action, because this is the half of the API that crosses into
4//! C, WASM, Python and Dart, and a single tagged value binds far more cheaply than a wide surface.
5
6use alloc::string::String;
7
8/// Whether we are still composing a message.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export, export_to = "obby.ts"))]
12#[cfg_attr(feature = "ts", ts(rename = "TypingState"))]
13#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
14pub enum Typing {
15 /// Typing right now.
16 Active,
17 /// Stopped, with text still in the box.
18 Paused,
19 /// Stopped, with the box empty.
20 Done,
21}
22
23impl Typing {
24 pub(crate) fn as_str(self) -> &'static str {
25 match self {
26 Self::Active => "active",
27 Self::Paused => "paused",
28 Self::Done => "done",
29 }
30 }
31}
32
33/// Something to do on this connection.
34#[derive(Debug, Clone, PartialEq, Eq)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36#[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export, export_to = "obby.ts"))]
37#[cfg_attr(feature = "serde", serde(tag = "type", rename_all = "snake_case"))]
38#[non_exhaustive]
39pub enum Command {
40 /// Join a channel.
41 Join {
42 /// The channel to join.
43 channel: String,
44 /// Its key, when it has one.
45 key: Option<String>,
46 },
47 /// Leave a channel.
48 Part {
49 /// The channel to leave.
50 channel: String,
51 /// Why, shown to the others in it.
52 reason: Option<String>,
53 },
54 /// Say something to a channel or a person.
55 SendMessage {
56 /// Where to say it.
57 target: String,
58 /// What to say.
59 text: String,
60 },
61 /// Send a notice, which by convention must never be auto-replied to.
62 SendNotice {
63 /// Where to send it.
64 target: String,
65 /// What to send.
66 text: String,
67 },
68 /// Send a `CTCP ACTION`, the third-person form.
69 SendAction {
70 /// Where to send it.
71 target: String,
72 /// What we are doing.
73 text: String,
74 },
75 /// Change our nick.
76 SetNick {
77 /// The nick to take.
78 nick: String,
79 },
80 /// Set or clear a channel topic.
81 SetTopic {
82 /// The channel.
83 channel: String,
84 /// The new topic, or nothing to clear it.
85 topic: Option<String>,
86 },
87 /// Mark ourselves away, or come back.
88 SetAway {
89 /// The away message, or nothing to come back.
90 message: Option<String>,
91 },
92 /// Say we are typing, so others can show it.
93 SetTyping {
94 /// Who we are typing to.
95 target: String,
96 /// How far along we are.
97 state: Typing,
98 },
99 /// React to a message with an emoji.
100 AddReaction {
101 /// The channel or person the message is in.
102 target: String,
103 /// The message reacted to.
104 msgid: String,
105 /// The emoji.
106 emoji: String,
107 },
108 /// Take a reaction back.
109 RemoveReaction {
110 /// The channel or person the message is in.
111 target: String,
112 /// The message.
113 msgid: String,
114 /// The emoji to remove.
115 emoji: String,
116 },
117 /// Ask the server to delete a message.
118 RedactMessage {
119 /// Where the message is.
120 target: String,
121 /// The message to delete.
122 msgid: String,
123 /// Why, when the server wants a reason.
124 reason: Option<String>,
125 },
126 /// Tell the server how far we have read.
127 MarkRead {
128 /// The channel or person.
129 target: String,
130 /// The last message read, in milliseconds since the Unix epoch. The engine writes the
131 /// `server-time` the wire wants.
132 #[cfg_attr(feature = "ts", ts(type = "number"))]
133 at_ms: u64,
134 },
135 /// Ask for older messages than the ones we hold.
136 ///
137 /// With no `before_msgid`, this asks for the most recent, which is what a fresh window wants.
138 FetchHistory {
139 /// The channel or person.
140 target: String,
141 /// Fetch messages older than the message with this id.
142 before_msgid: Option<String>,
143 /// How many to ask for.
144 limit: u16,
145 },
146 /// Set one of our own metadata keys, or clear it.
147 SetMetadata {
148 /// The key, such as `display-name`, `color` or `avatar`.
149 key: String,
150 /// The value, or nothing to clear the key.
151 value: Option<String>,
152 },
153 /// Ask to be told when these metadata keys change on anyone we can see.
154 SubscribeMetadata {
155 /// The keys to watch.
156 keys: alloc::vec::Vec<String>,
157 },
158 /// Ask the server everything it will say about someone.
159 ///
160 /// The reply is nine numerics; the engine collects them and reports the whole record once.
161 Whois {
162 /// Who to ask about.
163 nick: String,
164 },
165 /// Rename a channel, keeping everyone in it and everything said in it.
166 RenameChannel {
167 /// The channel as it is called now.
168 channel: String,
169 /// What to call it.
170 new_name: String,
171 /// Why, shown to the others in it.
172 reason: Option<String>,
173 },
174 /// Make an invitation link to a channel, or to the network when no channel is named.
175 CreateInviteLink {
176 /// The channel it joins, or nothing to invite to the network.
177 channel: Option<String>,
178 /// What it is for.
179 description: Option<String>,
180 },
181 /// Ask for the invitation links we have made.
182 ListInviteLinks,
183 /// Withdraw an invitation link.
184 DeleteInviteLink {
185 /// Which one, from [`Command::ListInviteLinks`].
186 share_id: String,
187 },
188 /// Redeem an invitation code. Only before registering, which is the point of it.
189 RedeemInviteCode {
190 /// The code, which is the share id of the link that carried it.
191 code: String,
192 },
193 /// Mint a bearer token for one of the network's services, such as its file host.
194 GenerateToken {
195 /// Which service the token is for, such as `FILEHOST`.
196 service: String,
197 },
198 /// Watch these nicks, so the server says when they come and go.
199 WatchNicks {
200 /// The nicks to watch.
201 nicks: alloc::vec::Vec<String>,
202 },
203 /// Stop watching these nicks.
204 UnwatchNicks {
205 /// The nicks to stop watching.
206 nicks: alloc::vec::Vec<String>,
207 },
208 /// Send a voice signalling frame to a room.
209 ///
210 /// The frame is the host's to build, because everything in it comes from the media stack the
211 /// core deliberately knows nothing about.
212 #[cfg(feature = "voice")]
213 SendVoiceSignal {
214 /// The channel to signal in.
215 channel: String,
216 /// The frame. The engine encodes it as the JSON that travels in the tag.
217 signal: crate::voice::Signal,
218 },
219 /// Leave the network.
220 Quit {
221 /// Why.
222 reason: Option<String>,
223 },
224 /// Send a line we do not model. The escape hatch, so a host is never stuck waiting for us.
225 SendRawLine {
226 /// The line, without its terminator.
227 line: String,
228 },
229}