trac-peer 0.0.67 → 0.0.69

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "trac-peer",
3
3
  "main": "src/index.js",
4
- "version": "0.0.67",
4
+ "version": "0.0.69",
5
5
  "type": "module",
6
6
  "dependencies": {
7
7
  "autobase": "7.0.45",
package/src/check.js CHANGED
@@ -71,6 +71,7 @@ class Check {
71
71
  this._feature = this.compileFeature();
72
72
  this._add_writer = this.compileAddWriter();
73
73
  this._key = this.compileKey();
74
+ this._update_admin = this.compileUpdateAdmin();
74
75
  this._nick = this.compileNick();
75
76
  this._mute = this.compileMute();
76
77
  this._delete_message = this.compileDeleteMessage();
@@ -135,7 +136,8 @@ class Check {
135
136
  mod : { type : "boolean" },
136
137
  type : { type : "string", min : 1 },
137
138
  address : { type : "is_hex" },
138
- user : { type : "is_hex" }
139
+ user : { type : "is_hex" },
140
+ deleted_by : { type : "is_hex" }
139
141
  }
140
142
  }
141
143
  };
@@ -228,6 +230,28 @@ class Check {
228
230
  return res === true;
229
231
  }
230
232
 
233
+ compileUpdateAdmin() {
234
+ const schema = {
235
+ nonce: { type : "string", min : 1 },
236
+ hash: { type : "is_hex" },
237
+ value : {
238
+ $$type: "object",
239
+ dispatch : {
240
+ $$type : "object",
241
+ admin : { type : "is_hex", nullable : true },
242
+ type : { type : "string", min : 1 },
243
+ address : { type : "is_hex" }
244
+ }
245
+ }
246
+ };
247
+ return this.validator.compile(schema);
248
+ }
249
+
250
+ updateAdmin(op){
251
+ const res = this._update_admin(op);
252
+ return res === true;
253
+ }
254
+
231
255
  setStatus(op){
232
256
  // currently same as addWriter
233
257
  return this.addWriter(op);
@@ -293,7 +317,8 @@ class Check {
293
317
  msg : { type : "string", min : 1 },
294
318
  type : { type : "string", min : 1 },
295
319
  address : { type : "is_hex" },
296
- deleted_by : { type : "is_hex", nullable : true }
320
+ deleted_by : { type : "is_hex", nullable : true },
321
+ reply_to : { type : "number", integer : true, min : 0, nullable : true },
297
322
  }
298
323
  }
299
324
  };
package/src/contract.js CHANGED
@@ -11,7 +11,7 @@ class Contract {
11
11
  this.message_handler = null;
12
12
  this.root = null;
13
13
 
14
- this.enter_execute_schema = this.protocol.peer.check.compile({
14
+ this.enter_execute_schema = this.protocol.peer.check.validator.compile({
15
15
  value : {
16
16
  $$type: "object",
17
17
  dispatch : {
@@ -21,7 +21,7 @@ class Contract {
21
21
  }
22
22
  });
23
23
 
24
- this.tx_schema = this.protocol.peer.check.compile({
24
+ this.tx_schema = this.protocol.peer.check.validator.compile({
25
25
  key : { type : "string", hex : null },
26
26
  value : {
27
27
  $$type: "object",
@@ -32,7 +32,7 @@ class Contract {
32
32
  }
33
33
  });
34
34
 
35
- this.address_schema = this.protocol.peer.check.compile({
35
+ this.address_schema = this.protocol.peer.check.validator.compile({
36
36
  value : {
37
37
  $$type: "object",
38
38
  dispatch : {
@@ -42,7 +42,7 @@ class Contract {
42
42
  }
43
43
  });
44
44
 
45
- this.textkey_schema = this.protocol.peer.check.compile({
45
+ this.textkey_schema = this.protocol.peer.check.validator.compile({
46
46
  key : { type : "string", min : 1 }
47
47
  });
48
48
  }
@@ -64,6 +64,7 @@ class Contract {
64
64
 
65
65
  this.tx = op.type === 'tx' ? op.key : null;
66
66
  this.op = op.value.dispatch;
67
+ this.value = this.op.value !== undefined ? this.op.value : null;
67
68
  this.node = node;
68
69
  this.storage = storage;
69
70
  this.root = op;
@@ -99,7 +100,7 @@ class Contract {
99
100
  }
100
101
 
101
102
  addSchema(type, schema){
102
- this.schemata[type] = this.protocol.peer.check.compile(schema);
103
+ this.schemata[type] = this.protocol.peer.check.validator.compile(schema);
103
104
  }
104
105
 
105
106
  addFeature(type, func) {
@@ -132,8 +133,9 @@ class Contract {
132
133
  async put(key, value){
133
134
  if(typeof this.storage === "undefined" || this.storage === null) throw new Error('put(key,value): storage undefined');
134
135
  if(key.startsWith('sh/') || key.startsWith('tx/') || key === 'msgl' || key.startsWith('kcin/') || key.startsWith('delm/') ||
135
- key.startsWith('msg/') || key === 'admin' || key === 'auto_add_writers' || key.startsWith('nick/') || key.startsWith('mod/') ||
136
- key === 'chat_status' || key.startsWith('mtd/') || key === 'delml' || key === 'wlst' || key.startsWith('wl/'))
136
+ key.startsWith('umsg/') || key.startsWith('umsg/') || key.startsWith('msgl/') || key === 'admin' || key === 'auto_add_writers'
137
+ || key.startsWith('nick/') || key.startsWith('mod/') || key === 'chat_status' || key.startsWith('mtd/') || key === 'delml' ||
138
+ key === 'wlst' || key.startsWith('wl/'))
137
139
  throw Error('put(key,value): ' + key + 'is reserved');
138
140
  return await this.storage.put(key, value);
139
141
  }
package/src/functions.js CHANGED
@@ -105,7 +105,7 @@ export function jsonStringify(value){
105
105
 
106
106
  export async function setWhitelistStatus(input, peer){
107
107
  const splitted = yargs(input).parse();
108
- const value = splitted.user;
108
+ const value = ''+splitted.user;
109
109
  const status = parseInt(splitted.status) === 1;
110
110
  const nonce = Math.random() + '-' + Date.now();
111
111
  const signature = { dispatch : {
@@ -133,7 +133,7 @@ export async function enableWhitelist(input, peer){
133
133
 
134
134
  export async function deleteMessage(input, peer){
135
135
  const splitted = yargs(input).parse();
136
- const value = splitted.id;
136
+ const value = parseInt(splitted.id);
137
137
  const nonce = Math.random() + '-' + Date.now();
138
138
  const signature = { dispatch : {
139
139
  type : 'deleteMessage',
@@ -144,9 +144,22 @@ export async function deleteMessage(input, peer){
144
144
  await peer.base.append({type: 'deleteMessage', value: signature, hash : hash, nonce: nonce });
145
145
  }
146
146
 
147
+ export async function updateAdmin(input, peer){
148
+ const splitted = yargs(input).parse();
149
+ const value = ''+splitted.address === 'null' ? null : ''+splitted.address;
150
+ const nonce = Math.random() + '-' + Date.now();
151
+ const signature = { dispatch : {
152
+ type : 'updateAdmin',
153
+ admin: value,
154
+ address : peer.wallet.publicKey
155
+ }};
156
+ const hash = peer.wallet.sign(JSON.stringify(signature) + nonce);
157
+ await peer.base.append({type: 'updateAdmin', value: signature, hash : hash, nonce: nonce });
158
+ }
159
+
147
160
  export async function setMod(input, peer){
148
161
  const splitted = yargs(input).parse();
149
- const value = splitted.user;
162
+ const value = ''+splitted.user;
150
163
  const mod = parseInt(splitted.mod) === 1;
151
164
  const nonce = Math.random() + '-' + Date.now();
152
165
  const signature = { dispatch : {
@@ -161,7 +174,7 @@ export async function setMod(input, peer){
161
174
 
162
175
  export async function muteStatus(input, peer){
163
176
  const splitted = yargs(input).parse();
164
- const value = splitted.user;
177
+ const value = ''+splitted.user;
165
178
  const muted = parseInt(splitted.muted) === 1;
166
179
  const nonce = Math.random() + '-' + Date.now();
167
180
  const signature = { dispatch : {
@@ -176,10 +189,10 @@ export async function muteStatus(input, peer){
176
189
 
177
190
  export async function setNick(input, peer){
178
191
  const splitted = yargs(input).parse();
179
- const value = splitted.nick;
192
+ const value = ''+splitted.nick;
180
193
  let user = null;
181
194
  if(splitted.user !== undefined){
182
- user = splitted.user;
195
+ user = ''+splitted.user;
183
196
  }
184
197
  const nonce = Math.random() + '-' + Date.now();
185
198
  const signature = { dispatch : {
@@ -195,6 +208,7 @@ export async function setNick(input, peer){
195
208
  export async function postMessage(input, peer){
196
209
  const splitted = yargs(input).parse();
197
210
  if(typeof splitted.message === "boolean" || splitted.message === undefined) throw new Error('Empty message not allowed');
211
+ const reply_to = splitted.reply_to !== undefined ? parseInt(splitted.reply_to) : null;
198
212
  const value = '' + splitted.message;
199
213
  const nonce = Math.random() + '-' + Date.now();
200
214
  const signature = { dispatch : {
@@ -202,7 +216,8 @@ export async function postMessage(input, peer){
202
216
  msg: value,
203
217
  address : peer.wallet.publicKey,
204
218
  attachments : [],
205
- deleted_by : null
219
+ deleted_by : null,
220
+ reply_to : reply_to
206
221
  }};
207
222
  const hash = peer.wallet.sign(JSON.stringify(signature) + nonce);
208
223
  await peer.base.append({type: 'msg', value: signature, hash : hash, nonce: nonce });
@@ -210,7 +225,7 @@ export async function postMessage(input, peer){
210
225
 
211
226
  export async function setChatStatus(input, peer){
212
227
  const splitted = yargs(input).parse();
213
- const value = splitted.enabled === 1 ? 'on' : 'off';
228
+ const value = parseInt(splitted.enabled) === 1 ? 'on' : 'off';
214
229
  const nonce = Math.random() + '-' + Date.now();
215
230
  if(value !== 'on' && value !== 'off') throw new Error('setChatStatus: use on and off values.');
216
231
  const msg = { type: 'setChatStatus', key: value }
@@ -223,7 +238,7 @@ export async function setChatStatus(input, peer){
223
238
 
224
239
  export async function setAutoAddWriters(input, peer){
225
240
  const splitted = yargs(input).parse();
226
- const value = splitted.enabled === 1 ? 'on' : 'off';
241
+ const value = parseInt(splitted.enabled) === 1 ? 'on' : 'off';
227
242
  const nonce = Math.random() + '-' + Date.now();
228
243
  if(value !== 'on' && value !== 'off') throw new Error('setAutoAddWriters: use on and off values.');
229
244
  const msg = { type: 'setAutoAddWriters', key: value }
@@ -236,7 +251,7 @@ export async function setAutoAddWriters(input, peer){
236
251
 
237
252
  export async function addAdmin(input, peer){
238
253
  const splitted = yargs(input).parse();
239
- const publicKey = splitted.address;
254
+ const publicKey = ''+splitted.address;
240
255
  await peer.base.append({ type: 'addAdmin', key: publicKey });
241
256
  }
242
257
 
@@ -245,18 +260,18 @@ export async function addWriter(input, peer){
245
260
  const parsed = yargs(input).parse();
246
261
  const nonce = Math.random() + '-' + Date.now();
247
262
  if(splitted[0] === '/add_indexer'){
248
- const msg = { type: 'addIndexer', key: parsed.key }
263
+ const msg = { type: 'addIndexer', key: ''+parsed.key }
249
264
  const signature = {
250
265
  msg: msg
251
266
  };
252
267
  const hash = peer.wallet.sign(JSON.stringify(msg) + nonce);
253
268
  peer.emit('announce', { op : 'append_writer', type: 'addIndexer', key: parsed.key, value: signature, hash: hash, nonce: nonce });
254
269
  } else if(splitted[0] === '/add_writer') {
255
- const msg = { type: 'addWriter', key: parsed.key }
270
+ const msg = { type: 'addWriter', key: ''+parsed.key }
256
271
  const signature = {
257
272
  msg: msg
258
273
  };
259
274
  const hash = peer.wallet.sign(JSON.stringify(msg) + nonce);
260
- peer.emit('announce', { op : 'append_writer', type: 'addWriter', key: parsed.key, value: signature, hash: hash, nonce : nonce });
275
+ peer.emit('announce', { op : 'append_writer', type: 'addWriter', key: ''+parsed.key, value: signature, hash: hash, nonce : nonce });
261
276
  }
262
277
  }
package/src/index.js CHANGED
@@ -11,7 +11,7 @@ import w from 'protomux-wakeup';
11
11
  const wakeup = new w();
12
12
  import {addWriter, addAdmin, setAutoAddWriters, setChatStatus, setMod, deleteMessage,
13
13
  enableWhitelist, postMessage, jsonStringify, visibleLength, setNick,
14
- muteStatus, setWhitelistStatus} from "./functions.js";
14
+ muteStatus, setWhitelistStatus, updateAdmin} from "./functions.js";
15
15
  import Check from "./check.js";
16
16
  export {default as Protocol} from "./protocol.js";
17
17
  export {default as Contract} from "./contract.js";
@@ -76,7 +76,7 @@ export class Peer extends ReadyResource {
76
76
  const batch = view.batch();
77
77
 
78
78
  for (const node of nodes) {
79
- if(false === await this.check.node(node)) continue;
79
+ if(false === this.check.node(node)) continue;
80
80
  const op = node.value;
81
81
  if (op.type === 'tx') {
82
82
  if(false === this.check.tx(op)) continue;
@@ -84,7 +84,7 @@ export class Peer extends ReadyResource {
84
84
  const msb_view_session = _this.msb.base.view.checkout(op.value.msbsl);
85
85
  const post_tx = await msb_view_session.get(op.key);
86
86
  await msb_view_session.close();
87
- if(false === await this.check.postTx(post_tx)) continue;
87
+ if(false === this.check.postTx(post_tx)) continue;
88
88
  if (null !== str_dispatch &&
89
89
  null === await batch.get('tx/'+op.key) &&
90
90
  post_tx.value.tx === op.key &&
@@ -94,7 +94,7 @@ export class Peer extends ReadyResource {
94
94
  console.log(`${op.key} appended. Signed length:`, _this.base.view.core.signedLength);
95
95
  }
96
96
  } else if(op.type === 'msg') {
97
- if(false === await this.check.msg(op)) continue;
97
+ if(false === this.check.msg(op)) continue;
98
98
  const admin = await batch.get('admin');
99
99
  let muted = false;
100
100
  let whitelisted = true;
@@ -126,15 +126,23 @@ export class Peer extends ReadyResource {
126
126
  } else {
127
127
  len = len.value;
128
128
  }
129
+ let user_len = await batch.get('umsgl/'+op.value.dispatch.address);
130
+ if(null === user_len) {
131
+ user_len = 0;
132
+ } else {
133
+ user_len = user_len.value;
134
+ }
129
135
  await batch.put('msg/'+len, op.value.dispatch);
136
+ await batch.put('umsg/'+user_len, 'msg/'+len);
130
137
  await batch.put('msgl', len + 1);
138
+ await batch.put('umsgl/'+op.value.dispatch.address, user_len + 1);
131
139
  await _this.contract_instance.execute(op, node, batch);
132
140
  const nick = await batch.get('nick/'+op.value.dispatch.address);
133
141
  console.log(`#${len + 1} | ${nick !== null ? nick.value : op.value.dispatch.address}: ${op.value.dispatch.msg}`);
134
142
  }
135
143
  await batch.put('sh/'+op.hash, '');
136
144
  } else if (op.type === 'feature') {
137
- if(false === await this.check.feature(op)) continue;
145
+ if(false === this.check.feature(op)) continue;
138
146
  const str_dispatch_value = jsonStringify(op.value.dispatch.value);
139
147
  const admin = await batch.get('admin');
140
148
  if(null !== admin &&
@@ -147,7 +155,7 @@ export class Peer extends ReadyResource {
147
155
  }
148
156
  await batch.put('sh/'+op.value.dispatch.hash, '');
149
157
  } else if (op.type === 'addIndexer') {
150
- if(false === await this.check.addIndexer(op)) continue;
158
+ if(false === this.check.addIndexer(op)) continue;
151
159
  const str_msg = jsonStringify(op.value.msg);
152
160
  const admin = await batch.get('admin');
153
161
  if(null !== admin &&
@@ -163,7 +171,7 @@ export class Peer extends ReadyResource {
163
171
  }
164
172
  await batch.put('sh/'+op.hash, '');
165
173
  } else if (op.type === 'addWriter') {
166
- if(false === await this.check.addWriter(op)) continue;
174
+ if(false === this.check.addWriter(op)) continue;
167
175
  const str_msg = jsonStringify(op.value.msg);
168
176
  const admin = await batch.get('admin');
169
177
  if(null !== admin &&
@@ -179,7 +187,7 @@ export class Peer extends ReadyResource {
179
187
  }
180
188
  await batch.put('sh/'+op.hash, '');
181
189
  } else if (op.type === 'setChatStatus') {
182
- if(false === await this.check.setStatus(op)) continue;
190
+ if(false === this.check.setStatus(op)) continue;
183
191
  const str_msg = jsonStringify(op.value.msg);
184
192
  const admin = await batch.get('admin');
185
193
  if(null !== admin && op.value.msg.key === op.key &&
@@ -194,7 +202,7 @@ export class Peer extends ReadyResource {
194
202
  }
195
203
  await batch.put('sh/'+op.hash, '');
196
204
  } else if (op.type === 'setAutoAddWriters') {
197
- if(false === await this.check.setStatus(op)) continue;
205
+ if(false === this.check.setStatus(op)) continue;
198
206
  const str_msg = jsonStringify(op.value.msg);
199
207
  const admin = await batch.get('admin');
200
208
  if(null !== admin && op.value.msg.key === op.key &&
@@ -209,7 +217,7 @@ export class Peer extends ReadyResource {
209
217
  }
210
218
  await batch.put('sh/'+op.hash, '');
211
219
  } else if (op.type === 'autoAddWriter') {
212
- if(false === await this.check.key(op)) continue;
220
+ if(false === this.check.key(op)) continue;
213
221
  const auto_add_writers = await batch.get('auto_add_writers');
214
222
  if(null !== auto_add_writers && auto_add_writers.value === 'on'){
215
223
  const writerKey = b4a.from(op.key, 'hex');
@@ -217,14 +225,27 @@ export class Peer extends ReadyResource {
217
225
  }
218
226
  console.log(`Writer auto added: ${op.key}`);
219
227
  } else if (op.type === 'addAdmin') {
220
- if(false === await this.check.key(op)) continue;
228
+ if(false === this.check.key(op)) continue;
221
229
  const bootstrap = Buffer(node.from.key).toString('hex')
222
230
  if(null === await batch.get('admin') && bootstrap === _this.bootstrap){
223
231
  await batch.put('admin', op.key);
224
232
  console.log(`Admin added: ${op.key}`);
225
233
  }
234
+ } else if (op.type === 'updateAdmin') {
235
+ if(false === this.check.updateAdmin(op)) continue;
236
+ const admin = await batch.get('admin');
237
+ const str_value = jsonStringify(op.value);
238
+ if(null !== admin && null !== str_value &&
239
+ null === await batch.get('sh/'+op.hash)){
240
+ const verified = _this.wallet.verify(op.hash, str_value + op.nonce, admin.value);
241
+ if(verified) {
242
+ await batch.put('admin', op.value.dispatch.admin);
243
+ console.log(`Changed admin ${admin.value} to ${op.value.dispatch.admin}`);
244
+ }
245
+ }
246
+ await batch.put('sh/'+op.hash, '');
226
247
  } else if(op.type === 'setNick') {
227
- if(false === await this.check.nick(op)) continue;
248
+ if(false === this.check.nick(op)) continue;
228
249
  const taken = await batch.get('kcin/'+op.value.dispatch.nick);
229
250
  const chat_status = await batch.get('chat_status');
230
251
  const str_value = jsonStringify(op.value);
@@ -258,7 +279,7 @@ export class Peer extends ReadyResource {
258
279
  }
259
280
  await batch.put('sh/'+op.hash, '');
260
281
  } else if(op.type === 'muteStatus') {
261
- if(false === await this.check.mute(op)) continue;
282
+ if(false === this.check.mute(op)) continue;
262
283
  const admin = await batch.get('admin');
263
284
  const str_value = jsonStringify(op.value);
264
285
  if(null !== admin && null !== str_value &&
@@ -279,7 +300,7 @@ export class Peer extends ReadyResource {
279
300
  }
280
301
  await batch.put('sh/'+op.hash, '');
281
302
  } else if(op.type === 'deleteMessage') {
282
- if(false === await this.check.deleteMessage(op)) continue;
303
+ if(false === this.check.deleteMessage(op)) continue;
283
304
  const admin = await batch.get('admin');
284
305
  const str_value = jsonStringify(op.value);
285
306
  if(null !== admin && null !== str_value &&
@@ -316,7 +337,7 @@ export class Peer extends ReadyResource {
316
337
  }
317
338
  await batch.put('sh/'+op.hash, '');
318
339
  } else if(op.type === 'setMod') {
319
- if(false === await this.check.mod(op)) continue;
340
+ if(false === this.check.mod(op)) continue;
320
341
  const admin = await batch.get('admin');
321
342
  const str_value = jsonStringify(op.value);
322
343
  if(null !== admin && null !== str_value &&
@@ -329,7 +350,7 @@ export class Peer extends ReadyResource {
329
350
  }
330
351
  await batch.put('sh/'+op.hash, '');
331
352
  } else if(op.type === 'setWhitelistStatus') {
332
- if(false === await this.check.whitelistStatus(op)) continue;
353
+ if(false === this.check.whitelistStatus(op)) continue;
333
354
  const admin = await batch.get('admin');
334
355
  const str_value = jsonStringify(op.value);
335
356
  if(null !== admin && null !== str_value &&
@@ -342,7 +363,7 @@ export class Peer extends ReadyResource {
342
363
  }
343
364
  await batch.put('sh/'+op.hash, '');
344
365
  } else if(op.type === 'enableWhitelist') {
345
- if(false === await this.check.enableWhitelist(op)) continue;
366
+ if(false === this.check.enableWhitelist(op)) continue;
346
367
  const admin = await batch.get('admin');
347
368
  const str_value = jsonStringify(op.value);
348
369
  if(null !== admin && null !== str_value &&
@@ -563,13 +584,14 @@ export class Peer extends ReadyResource {
563
584
  console.log(' ');
564
585
  console.log('- Setup Commands:');
565
586
  console.log('- /add_admin | Works only once and only on bootstrap node! Enter a wallet address to assign admin rights: \'/add_admin --address "<address>"\'.');
587
+ console.log('- /update_admin | Existing admins may transfer admin ownership. Enter "null" as address to waive admin rights for this peer entirely: \'/add_admin --address "<address>"\'.');
566
588
  console.log('- /add_indexer | Only admin. Enter a peer writer key to get included as indexer for this network: \'/add_indexer --key "<key>"\'.');
567
589
  console.log('- /add_writer | Only admin. Enter a peer writer key to get included as writer for this network: \'/add_writer --key "<key>"\'.');
568
590
  console.log('- /set_auto_add_writers | Only admin. Allow any peer to join as writer automatically: \'/set_auto_add_writers --enabled 1\'');
569
591
  console.log(' ');
570
592
  console.log('- Chat Commands:');
571
593
  console.log('- /set_chat_status | Only admin. Enable/disable the built-in chat system: \'/set_chat_status --enabled 1\'. The chat system is disabled by default.');
572
- console.log('- /post | Post a message: \'/post --message "Hello"\'. Chat must be enabled.');
594
+ console.log('- /post | Post a message: \'/post --message "Hello"\'. Chat must be enabled. Optionally use \'--reply_to <message id>\' to respond to a desired message.');
573
595
  console.log('- /set_nick | Change your nickname like this \'/set_nick --nick "Peter"\'. Chat must be enabled. Can be edited by admin and mods using the optional --user <address> flag.');
574
596
  console.log('- /mute_status | Only admin and mods. Mute or unmute a user by their address: \'/mute_status --user "<address>" --muted 1\'.');
575
597
  console.log('- /set_mod | Only admin. Set a user as mod: \'/set_mod --user "<address>" --mod 1\'.');
@@ -604,6 +626,8 @@ export class Peer extends ReadyResource {
604
626
  await addWriter(input, this);
605
627
  } else if (input.startsWith('/add_admin')) {
606
628
  await addAdmin(input, this);
629
+ } else if (input.startsWith('/update_admin')) {
630
+ await updateAdmin(input, this);
607
631
  } else if (input.startsWith('/set_auto_add_writers')) {
608
632
  await setAutoAddWriters(input, this);
609
633
  } else if (input.startsWith('/set_chat_status')) {