@rustwirebot/rustplus.js 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +351 -0
  3. package/camera.js +425 -0
  4. package/cli/index.js +308 -0
  5. package/cli/pair.html +49 -0
  6. package/docs/API.md +101 -0
  7. package/docs/DownloadBundle.md +7 -0
  8. package/docs/PairingFlow.md +19 -0
  9. package/donate.md +10 -0
  10. package/examples/10_shoot_autoturret.js +100 -0
  11. package/examples/1_send_team_chat.js +16 -0
  12. package/examples/2_turn_smart_switch_on.js +21 -0
  13. package/examples/3_turn_smart_switch_off.js +21 -0
  14. package/examples/4_entity_changed_broadcasts.js +58 -0
  15. package/examples/5_download_map_jpeg.js +22 -0
  16. package/examples/6_async_requests.js +35 -0
  17. package/examples/7_render_camera.js +34 -0
  18. package/examples/8_move_ptz_camera.js +56 -0
  19. package/examples/9_zoom_ptz_camera.js +37 -0
  20. package/package.json +48 -0
  21. package/rustplus.js +380 -0
  22. package/rustplus.js.svg +34 -0
  23. package/rustplus.proto +431 -0
  24. package/vendor/push-receiver/LICENSE +21 -0
  25. package/vendor/push-receiver/NOTICE.md +32 -0
  26. package/vendor/push-receiver/android/fcm.js +134 -0
  27. package/vendor/push-receiver/client.js +216 -0
  28. package/vendor/push-receiver/constants.js +53 -0
  29. package/vendor/push-receiver/fcm/index.js +52 -0
  30. package/vendor/push-receiver/fcm/server-key/index.js +67 -0
  31. package/vendor/push-receiver/gcm/android_checkin.proto +96 -0
  32. package/vendor/push-receiver/gcm/checkin.proto +155 -0
  33. package/vendor/push-receiver/gcm/index.js +128 -0
  34. package/vendor/push-receiver/index.js +17 -0
  35. package/vendor/push-receiver/mcs.proto +328 -0
  36. package/vendor/push-receiver/parser.js +276 -0
  37. package/vendor/push-receiver/register/index.js +18 -0
  38. package/vendor/push-receiver/utils/base64/index.js +15 -0
  39. package/vendor/push-receiver/utils/decrypt/index.js +23 -0
  40. package/vendor/push-receiver/utils/http-request/index.js +43 -0
  41. package/vendor/push-receiver/utils/request/index.js +27 -0
  42. package/vendor/push-receiver/utils/timeout/index.js +7 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) Liam Cottle (original author, https://github.com/liamcottle/rustplus.js)
4
+ Copyright (c) 2026 BotForge Studios (fork maintenance and republishing as @rustwire/rustplus.js)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,351 @@
1
+ > **Note:** This is a maintained fork of [liamcottle/rustplus.js](https://github.com/liamcottle/rustplus.js), republished under the `@rustwire` npm scope by BotForge Studios so it can be installed/run as `npx @rustwirebot/rustplus.js <command>`. All credit for the original library and protobuf reverse-engineering goes to Liam Cottle. This fork is distributed under the same MIT license — see [LICENSE](./LICENSE). The `@liamcottle/push-receiver` dependency used by the `fcm-register`/`fcm-listen` CLI commands has also been vendored locally under [`vendor/push-receiver`](./vendor/push-receiver) (with its own attribution/NOTICE) so this package keeps working even if that upstream npm package is ever removed.
2
+
3
+ <p align="center">
4
+ <img src="./rustplus.js.svg" width="400"></a>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@rustwirebot/rustplus.js"><img src="https://img.shields.io/npm/dt/@rustwirebot/rustplus.js" alt="npm"/></a>
9
+ <a href="https://discord.gg/APQSQZNV7t"><img src="https://img.shields.io/badge/Discord-Liam%20Cottle's%20Discord-%237289DA?style=flat&logo=discord" alt="discord"/></a>
10
+ <a href="https://twitter.com/liamcottle"><img src="https://img.shields.io/badge/Twitter-@liamcottle-%231DA1F2?style=flat&logo=twitter" alt="twitter"/></a>
11
+ <br/>
12
+ <a href="https://ko-fi.com/liamcottle"><img src="https://img.shields.io/badge/Donate%20a%20Coffee-liamcottle-yellow?style=flat&logo=buy-me-a-coffee" alt="donate on ko-fi"/></a>
13
+ <a href="./donate.md"><img src="https://img.shields.io/badge/Donate%20Bitcoin-bc1qy22smke8n4c54evdxmp7lpy9p0e6m9tavtlg2q-%23FF9900?style=flat&logo=bitcoin" alt="donate bitcoin"/></a>
14
+ </p>
15
+
16
+ This is an **unofficial** NodeJS library for interacting with Smart Switches, Smart Alarms and various other things in the PC game [Rust](https://store.steampowered.com/app/252490/Rust/).
17
+
18
+ It communicates with the [Rust Game Server](https://developer.valvesoftware.com/wiki/Rust_Dedicated_Server) via the WebSocket running on the port configured in your `server.cfg` as `app.port`.
19
+
20
+ The server owner needs to make sure their `app.port` has been configured and opened in their firewall.
21
+
22
+ Also, feel free to check out my new rust project [Atlas](https://github.com/liamcottle/atlas-for-rust). It's an interactive map experience for Rust.
23
+
24
+ ## Install
25
+
26
+ To use this library in your own NodeJS app, you can install it via `npm`.
27
+
28
+ ```
29
+ npm install @rustwirebot/rustplus.js
30
+ ```
31
+
32
+ ## Features
33
+
34
+ Below is a list of convenience methods that are implemented for common requests in the RustPlus library. Examples of these can be found in the [examples](#examples) section.
35
+
36
+ - `turnSmartSwitchOn` Turn Smart Switch on
37
+ - `turnSmartSwitchOff` Turn Smart Switch off
38
+ - `sendTeamMessage` Send messages to Team Chat
39
+ - `getEntityInfo` Get current state of a Smart Device
40
+ - `setEntityValue` Set the value of a Smart Device
41
+ - `getInfo` Get info about the Rust Server
42
+ - `getMap` Fetch map info, which inclues a jpeg image
43
+ - `getTime` Get the current in game time
44
+ - `getMapMarkers` Get map markers, such as vending machines and cargo/heli
45
+ - `getTeamInfo` Get list of team members and positions on map
46
+
47
+ More requests are available and can be found in the `AppRequest` message section of the [rustplus.proto](./rustplus.proto) protobuf file that I wrote by hand.
48
+
49
+ For requests that aren't available through a convenience method, you can still craft and send the requests manually with `sendRequest`, as shown below. Have a look in the protobuf file to know what data you need to send.
50
+
51
+ ```js
52
+ // Send Team Message without using convenience method
53
+ rustplus.sendRequest({
54
+ sendTeamMessage: {
55
+ message: "Message for Team Chat",
56
+ },
57
+ }, (message) => {
58
+ console.log(message);
59
+ });
60
+ ```
61
+
62
+ If you want a promise based API for sending requests, you can use `sendRequestAsync`. You won't be able to use the convenience methods, but it's very straightforward to craft the request payloads manually. Check [this example](./examples/6_async_requests.js) for using `sendRequestAsync`.
63
+
64
+ ## Examples
65
+
66
+ More code examples can be found in the [examples](./examples) directory.
67
+
68
+ ### Connecting
69
+
70
+ You will need to provide the following details to be able to connect:
71
+
72
+ - Server IP (or hostname)
73
+ - App Port (`app.port` in `server.cfg`)
74
+ - Player Id (Your Steam ID)
75
+ - Player Token ([Token from Server Pairing](#pairing))
76
+
77
+ ```js
78
+ const RustPlus = require('@rustwirebot/rustplus.js');
79
+ var rustplus = new RustPlus('ip', 'port', 'playerId', 'playerToken');
80
+
81
+ // wait until connected before sending commands
82
+ rustplus.on('connected', () => {
83
+
84
+ // ready to send requests
85
+ rustplus.sendTeamMessage('Hello from rustplus.js!');
86
+
87
+ });
88
+
89
+ // connect to rust server
90
+ rustplus.connect();
91
+ ```
92
+
93
+ > Note: You now need to call `connect` manually after creating a `RustPlus` instance. The library no longer automatically connects.
94
+
95
+ ### Turn Smart Switch On/Off
96
+
97
+ You can turn a Smart Switch on or off by calling `turnSmartSwitchOn` or `turnSmartSwitchOff` with the entity id of the Smart Switch.
98
+
99
+ An optional callback function can be provided as the second parameter which will be called when a response has been received from the server for this specific request.
100
+
101
+ ```js
102
+ rustplus.turnSmartSwitchOn(1234567, (message) => {
103
+ console.log("turnSmartSwitchOn response message: " + JSON.stringify(message));
104
+ return true;
105
+ });
106
+ ```
107
+
108
+ ### Send messages to Team Chat
109
+
110
+ You need to be in a team before you can send messages to team chat.
111
+
112
+ ```js
113
+ rustplus.sendTeamMessage('message to team chat');
114
+ ```
115
+
116
+ ### Get Entity Info
117
+
118
+ You can check the current status of a Smart Switch or Smart Alarm by calling `getEntityInfo` with the entity id.
119
+
120
+ ```js
121
+ rustplus.getEntityInfo(1234567, (message) => {
122
+ console.log("getEntityInfo response message: " + JSON.stringify(message));
123
+ return true;
124
+ });
125
+ ```
126
+
127
+ ### Entity Changed Broadcasts
128
+
129
+ Once you have called `getEntityInfo` at least once for an entity id, you will receive broadcast messages automatically from the Rust server when the entity's state changes between on and off.
130
+
131
+ If you don't call `getEntityInfo` at least once, you will never receive the broadcast.
132
+
133
+ You can capture the broadcast like so:
134
+
135
+ ```js
136
+ rustplus.on('message', (message) => {
137
+ if(message.broadcast && message.broadcast.entityChanged){
138
+
139
+ var entityChanged = message.broadcast.entityChanged;
140
+
141
+ var entityId = entityChanged.entityId;
142
+ var value = entityChanged.payload.value;
143
+
144
+ console.log("entity " + entityId + " is now " + (value ? "active" : "inactive"));
145
+
146
+ }
147
+ });
148
+ ```
149
+
150
+ #### Storage Monitor
151
+
152
+ The Storage Monitor that was recently added to Rust sends Entity Changed Broadcasts when items are added and removed from the Storage Container that the Storage Monitor is associated with.
153
+
154
+ You will receive two broadcasts for the Storage Monitor, one with the `entityChanged.payload.value` set to `true` and the second with the `entityChanged.payload.value` set to `false`. When using the official Rust+ app you'll see the storage monitor entity change to green, then back to grey.
155
+
156
+ Note that broadcasts are sent without player interaction only if tool cupboard changes to decaying state. Resources removed from a decay tick does not send a broadcast.
157
+
158
+ You can use the following snippet as an idea of how to listen for changes to a Storage Monitor and print out the current items in it.
159
+
160
+ As above, make sure to call `getEntityInfo` with the Storage Monitor entity id so you are sent the broadcasts by the server.
161
+
162
+ ```js
163
+ rustplus.on('message', (message) => {
164
+ if(message.broadcast && message.broadcast.entityChanged){
165
+
166
+ var entityChanged = message.broadcast.entityChanged;
167
+
168
+ var entityId = entityChanged.entityId;
169
+ var value = entityChanged.payload.value;
170
+ var capacity = entityChanged.payload.capacity;
171
+ var items = entityChanged.payload.items;
172
+
173
+ // only print info when second broadcast is received
174
+ if(!value){
175
+
176
+ console.log(`entity ${entityId} has a capacity of ${capacity}`);
177
+ console.log(`entity ${entityId} contains ${items.length} item(s)`);
178
+
179
+ // print out the items in this storage entity
180
+ items.forEach((item) => {
181
+ console.log(item);
182
+ });
183
+
184
+ }
185
+
186
+ }
187
+ });
188
+ ```
189
+
190
+ ## Handle Messages
191
+
192
+ A message is a payload of data sent to you from the Rust Server. This shouldn't be confused with Chat Messages.
193
+
194
+ When you send a request to the Rust Server, you can optionally provide a callback which will be invoked when a response is received from the server for that specific request.
195
+
196
+ If you return `true` from the callback, the response will be treated as handled.
197
+
198
+ When a message has been received and has not been handled by your callback, it will be emitted via the `message` event.
199
+
200
+ You can register a listener to catch all received messages like so:
201
+
202
+ ```js
203
+ rustplus.on('message', (message) => {
204
+ console.log("message received: " + JSON.stringify(message));
205
+ });
206
+ ```
207
+
208
+ Here's a list of the emitted events:
209
+
210
+ - `connecting`: When we are connecting to the Rust Server.
211
+ - `connected`: When we are connected to the Rust Server.
212
+ - `disconnected`: When we are disconnected from the Rust Server.
213
+ - `error`: When something goes wrong.
214
+ - `message`: When an `AppMessage` has been received from the Rust Server.
215
+ - `request`: When an `AppRequest` has been sent to the Rust Server.
216
+
217
+ ## CCTV Camera Frames
218
+
219
+ Check the [examples](./examples) on how to render and control CCTV Cameras, PTZ Cameras, Auto Turrets and Drones.
220
+
221
+ ## Pairing
222
+
223
+ In order to use this library, we need to get the Server Information to connect to the App WebSocket as well as get the Entity Ids of the Smart Alarms and Smart switches we want to interact with.
224
+
225
+ The way this works in the official Rust+ app is documented in the [Pairing Flow](docs/PairingFlow.md) document in the docs folder.
226
+
227
+ You can gather the required information in a couple of ways.
228
+
229
+ ### As a Rust Server Admin
230
+
231
+ If you just want to interact with your own private server for testing, you won't need to utilize the Rust Companion API server as you can already access all of the information you need from the server itself.
232
+
233
+ - You already have access to your `Server IP` and `App Port` configured in your `server.cfg` file.
234
+ - You can find your `playerToken` in the sqlite3 database file `player.tokens.db` with the following command on a Linux server. `sqlite3 player.tokens.db "select * from data;" ".exit"`
235
+ - You will get output like so: `xxxxxxxxxxxxxxxxx|yyyyyyyyy`
236
+ - `xxxxxxxxxxxxxxxxx` is the `playerId`
237
+ - `yyyyyyyyy` is the `playerToken`. (It can be a positive or negative integer.)
238
+ - As an admin you can use the command `lookingat_debug` to show/hide the entity id of what you are currently looking at. I like to bind it to a key with `bind o lookingat_debug`.
239
+
240
+ ### Using the Command Line Tool
241
+
242
+ I have put together a command line tool which will do everything required to receive Pairing Notifications from the Rust Companion API when you click the "Pair" buttons in game.
243
+
244
+ Before you can listen for Pairing Notifications, you need to register with FCM, Expo and link your Steam Account with Rust+. Conveniently, you can do this by running the following command.
245
+
246
+ ```
247
+ npx @rustwirebot/rustplus.js fcm-register
248
+ ```
249
+
250
+ A custom Google Chrome browser will be launched. This will take you to the Rust Companion website to log in with your Steam account.
251
+
252
+ > Note: You must have Google Chrome installed to use `fcm-register`
253
+
254
+ After successfully registering, you can listen for Pairing Notifications
255
+
256
+ ```
257
+ npx @rustwirebot/rustplus.js fcm-listen
258
+ ```
259
+
260
+ Example Output
261
+
262
+ ```
263
+ {
264
+ img: '',
265
+ port: '28017',
266
+ ip: 'your-server-ip',
267
+ name: "your-server-name",
268
+ id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
269
+ type: 'server',
270
+ url: '',
271
+ desc: 'your-server-description',
272
+ playerId: 'your-steam-id',
273
+ playerToken: 'your-player-token'
274
+ }
275
+ ```
276
+
277
+ The command line tool allows you to set a custom config file for saving and loading your credentials. This is helpful if you want to register on your local pc, and copy the config to another server.
278
+
279
+ ```
280
+ npx @rustwirebot/rustplus.js --config-file=/path/to/config.json <command>
281
+ ```
282
+
283
+ If you want to run the latest changes to the CLI tool, you can run it like so:
284
+
285
+ ```
286
+ git clone https://github.com/YOUR_GITHUB_USERNAME/rustwire-rustplus.js
287
+ cd rustplus.js
288
+ npm install
289
+ node cli/index.js <command>
290
+ ```
291
+
292
+ ## Connection Limits
293
+
294
+ The Rust game server enforces a limit on how many connections can be made to the Rust+ websocket, and how many connections can be made by the same IP Address at once.
295
+
296
+ - Max Connections: `500` is default
297
+ - Can be adjusted with server var `app.maxconnections`
298
+ - Max Connections per IP: `5` is default
299
+ - Can be adjusted with server var `app.maxconnectionsperip`
300
+
301
+ ## Rate Limits
302
+
303
+ The Rust game server enforces rate limits on requests sent to the Rust+ websocket. This is done with a [token bucket](https://en.wikipedia.org/wiki/Token_bucket) approach.
304
+
305
+ The token bucket gives you a maximum amount of tokens, and replenishes them over time at a fixed rate.
306
+
307
+ Here is a list of the rate limits enforced by the Rust game server:
308
+
309
+ - Requests per IP Address
310
+ - `50 tokens limit, 15 tokens replenished per second.`
311
+ - Requests per Player ID
312
+ - `25 tokens limit, 3 tokens replenished per second.`
313
+ - Requests for Server Pairing
314
+ - `5 tokens limit, 0.1 tokens replenished per second.`
315
+
316
+ Rate limits can be found in the `CompanionServer.Listener` class in `Assembly-CSharp.dll` from the game server files.
317
+
318
+ Below is the token cost per request type:
319
+
320
+ ```
321
+ Default: 1
322
+ --
323
+ CheckSubscription: 1
324
+ EntityInfo: 1
325
+ Info: 1
326
+ Map: 5
327
+ MapMarkers: 1
328
+ PromoteToLeader: 1
329
+ SendTeamChat: 2
330
+ SetEntityValue: 1
331
+ SetSubscription: 1
332
+ TeamInfo: 1
333
+ Time: 1
334
+ Camera Subscription: 1
335
+ Camera Movement: 0.01
336
+ ```
337
+
338
+ ## Hey Facepunch!
339
+
340
+ If you want this project taken down, feel free to message me! However this project only allows you to automate the same actions you can already do in the official Rust+ app.
341
+
342
+ I'm looking forward to seeing all of the projects the Rust community come up with! Here are some ideas I came up with:
343
+
344
+ - Discord Bot
345
+ - Sync Team Chat in-game and on Discord.
346
+ - Send messages to Discord when Smart Alarms are triggered.
347
+ - Send messages to Discord when Cargo, Heli or Crate events spawn on the map.
348
+ - Controlling Smart Devices via Discord messages.
349
+ - [Vending Machine Search Tool](https://github.com/liamcottle/atlas-for-rust)
350
+ - Find a specific item for sale on the map
351
+ - Statistics on what items are commonly sold, and for what prices.