neuronum 7.0.2__py3-none-any.whl → 7.0.4__py3-none-any.whl
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.
Potentially problematic release.
This version of neuronum might be problematic. Click here for more details.
- cli/main.py +488 -28
- {neuronum-7.0.2.dist-info → neuronum-7.0.4.dist-info}/METADATA +4 -4
- neuronum-7.0.4.dist-info/RECORD +10 -0
- neuronum-7.0.2.dist-info/RECORD +0 -10
- {neuronum-7.0.2.dist-info → neuronum-7.0.4.dist-info}/WHEEL +0 -0
- {neuronum-7.0.2.dist-info → neuronum-7.0.4.dist-info}/entry_points.txt +0 -0
- {neuronum-7.0.2.dist-info → neuronum-7.0.4.dist-info}/licenses/LICENSE.md +0 -0
- {neuronum-7.0.2.dist-info → neuronum-7.0.4.dist-info}/top_level.txt +0 -0
cli/main.py
CHANGED
|
@@ -249,14 +249,15 @@ def delete_cell():
|
|
|
249
249
|
|
|
250
250
|
|
|
251
251
|
@click.command()
|
|
252
|
-
|
|
252
|
+
@click.option('--blank', is_flag=True, help="Generate a Node Template without Stream and Transmitter")
|
|
253
|
+
def init_node(blank):
|
|
253
254
|
descr = click.prompt("Node description: Type up to 25 characters").strip()
|
|
254
255
|
if descr and len(descr) > 25:
|
|
255
256
|
click.echo("Description too long. Max 25 characters allowed.")
|
|
256
257
|
return
|
|
257
|
-
asyncio.run(async_init_node(descr))
|
|
258
|
+
asyncio.run(async_init_node(blank, descr))
|
|
258
259
|
|
|
259
|
-
async def async_init_node(descr):
|
|
260
|
+
async def async_init_node(blank, descr):
|
|
260
261
|
credentials_folder_path = Path.home() / ".neuronum"
|
|
261
262
|
env_path = credentials_folder_path / ".env"
|
|
262
263
|
|
|
@@ -312,21 +313,359 @@ async def async_init_node(descr):
|
|
|
312
313
|
env_path = project_path / ".env"
|
|
313
314
|
await asyncio.to_thread(env_path.write_text, f"NODE={nodeID}\nHOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
|
|
314
315
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
if blank is False:
|
|
317
|
+
stx_descr = f"{nodeID} App"
|
|
318
|
+
partners = ["private"]
|
|
319
|
+
stxID = await cell.create_stx(stx_descr, partners)
|
|
320
|
+
|
|
321
|
+
tx_descr = f"Greet {nodeID}"
|
|
322
|
+
key_values = {
|
|
323
|
+
"ping": "pong",
|
|
324
|
+
}
|
|
325
|
+
STX = stxID
|
|
326
|
+
label = "ping:pong"
|
|
327
|
+
partners = ["private"]
|
|
328
|
+
txID = await cell.create_tx(tx_descr, key_values, STX, label, partners)
|
|
329
|
+
|
|
330
|
+
app_path = project_path / "app.py"
|
|
331
|
+
app_path.write_text(f"""\
|
|
332
|
+
import asyncio
|
|
333
|
+
import neuronum
|
|
334
|
+
import os
|
|
335
|
+
import json
|
|
336
|
+
from dotenv import load_dotenv
|
|
337
|
+
from jinja2 import Environment, FileSystemLoader
|
|
318
338
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
339
|
+
env = Environment(loader=FileSystemLoader('.'))
|
|
340
|
+
template = env.get_template('ping.html')
|
|
341
|
+
|
|
342
|
+
with open('config.json', 'r') as f:
|
|
343
|
+
data = json.load(f)
|
|
344
|
+
terms_url = data['legals']['terms']
|
|
345
|
+
privacy_url = data['legals']['privacy_policy']
|
|
346
|
+
last_update = data['legals']['last_update']
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
load_dotenv()
|
|
350
|
+
host = os.getenv("HOST")
|
|
351
|
+
password = os.getenv("PASSWORD")
|
|
352
|
+
network = os.getenv("NETWORK")
|
|
353
|
+
synapse = os.getenv("SYNAPSE")
|
|
354
|
+
|
|
355
|
+
cell = neuronum.Cell(
|
|
356
|
+
host=host,
|
|
357
|
+
password=password,
|
|
358
|
+
network=network,
|
|
359
|
+
synapse=synapse
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
async def main():
|
|
363
|
+
STX = "{stxID}"
|
|
364
|
+
async for operation in cell.sync(STX):
|
|
365
|
+
txID = operation.get("txID")
|
|
366
|
+
client = operation.get("operator")
|
|
367
|
+
ts = operation.get("time")
|
|
368
|
+
data = operation.get("data")
|
|
369
|
+
operation_id = operation.get("operationID")
|
|
370
|
+
|
|
371
|
+
if txID == "{txID}":
|
|
372
|
+
|
|
373
|
+
def render_html_template(client, ts, data, operation_id, terms_url, privacy_url, last_update):
|
|
374
|
+
return template.render(client=client, ts=ts, data=data, operation_id=operation_id, terms_url=terms_url, privacy_url=privacy_url, last_update=last_update)
|
|
375
|
+
|
|
376
|
+
html_content = render_html_template(client, ts, data, operation_id, terms_url, privacy_url, last_update)
|
|
377
|
+
|
|
378
|
+
data = {{
|
|
379
|
+
"json": f"{{operation_id}} - Reply from {nodeID}: Pinged by {{client}} at {{ts}} with data: {{data}}",
|
|
380
|
+
"html": html_content
|
|
381
|
+
}}
|
|
382
|
+
|
|
383
|
+
await cell.notify(f"{{client}}", "{nodeID} Ping","Pinged successfully")
|
|
384
|
+
|
|
385
|
+
await cell.tx_response(txID, client, data)
|
|
386
|
+
|
|
387
|
+
asyncio.run(main())
|
|
388
|
+
""")
|
|
389
|
+
|
|
390
|
+
html_path = project_path / "ping.html"
|
|
391
|
+
html_content = f"""\
|
|
392
|
+
<!DOCTYPE html>
|
|
393
|
+
<html>
|
|
394
|
+
<head>
|
|
395
|
+
<style>
|
|
396
|
+
body {{
|
|
397
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
398
|
+
background-color: #121212;
|
|
399
|
+
color: #e0e0e0;
|
|
400
|
+
margin: 0;
|
|
401
|
+
padding: 0;
|
|
402
|
+
display: flex;
|
|
403
|
+
justify-content: center;
|
|
404
|
+
align-items: center;
|
|
405
|
+
min-height: 100vh;
|
|
406
|
+
}}
|
|
407
|
+
|
|
408
|
+
.container {{
|
|
409
|
+
background-color: #1e1e1e;
|
|
410
|
+
border-radius: 12px;
|
|
411
|
+
padding: 40px;
|
|
412
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
|
413
|
+
width: 100%;
|
|
414
|
+
max-width: 500px;
|
|
415
|
+
text-align: center;
|
|
416
|
+
box-sizing: border-box;
|
|
417
|
+
}}
|
|
418
|
+
|
|
419
|
+
.logo {{
|
|
420
|
+
width: 80px;
|
|
421
|
+
margin-bottom: 25px;
|
|
422
|
+
filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.1));
|
|
423
|
+
}}
|
|
424
|
+
|
|
425
|
+
h1 {{
|
|
426
|
+
font-size: 1.5em;
|
|
427
|
+
font-weight: 600;
|
|
428
|
+
margin-bottom: 5px;
|
|
429
|
+
color: #f5f5f5;
|
|
430
|
+
}}
|
|
431
|
+
|
|
432
|
+
.subtitle {{
|
|
433
|
+
font-size: 0.9em;
|
|
434
|
+
color: #a0a0a0;
|
|
435
|
+
margin-bottom: 30px;
|
|
436
|
+
}}
|
|
437
|
+
|
|
438
|
+
.data-row {{
|
|
439
|
+
background-color: #2a2a2a;
|
|
440
|
+
padding: 12px 15px;
|
|
441
|
+
border-radius: 8px;
|
|
442
|
+
margin-bottom: 10px;
|
|
443
|
+
display: flex;
|
|
444
|
+
justify-content: space-between;
|
|
445
|
+
align-items: center;
|
|
446
|
+
}}
|
|
447
|
+
|
|
448
|
+
.data-label {{
|
|
449
|
+
font-weight: 400;
|
|
450
|
+
color: #a0a0a0;
|
|
451
|
+
margin: 0;
|
|
452
|
+
}}
|
|
453
|
+
|
|
454
|
+
.data-value {{
|
|
455
|
+
font-weight: 500;
|
|
456
|
+
color: #e0e0e0;
|
|
457
|
+
margin: 0;
|
|
458
|
+
}}
|
|
459
|
+
|
|
460
|
+
.data-value.truncated {{
|
|
461
|
+
white-space: nowrap;
|
|
462
|
+
overflow: hidden;
|
|
463
|
+
text-overflow: ellipsis;
|
|
464
|
+
max-width: 60%;
|
|
465
|
+
}}
|
|
466
|
+
|
|
467
|
+
.data-value.client {{
|
|
468
|
+
color: #8cafff;
|
|
469
|
+
}}
|
|
470
|
+
.data-value.timestamp {{
|
|
471
|
+
color: #a1e8a1;
|
|
472
|
+
}}
|
|
473
|
+
.data-value.operation-id {{
|
|
474
|
+
color: #f7a2a2;
|
|
475
|
+
}}
|
|
476
|
+
.api-button {{
|
|
477
|
+
background: #01c07d 100%;
|
|
478
|
+
color: white;
|
|
479
|
+
border: none;
|
|
480
|
+
border-radius: 8px;
|
|
481
|
+
padding: 12px 24px;
|
|
482
|
+
font-size: 16px;
|
|
483
|
+
font-weight: bold;
|
|
484
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
485
|
+
cursor: pointer;
|
|
486
|
+
margin-top: 10px;
|
|
487
|
+
}}
|
|
488
|
+
</style>
|
|
489
|
+
</head>
|
|
490
|
+
<body>
|
|
491
|
+
<div class="container">
|
|
492
|
+
<img class="logo" src="https://neuronum.net/static/logo.png" alt="Neuronum Logo">
|
|
493
|
+
|
|
494
|
+
<h1>Reply from {nodeID}</h1>
|
|
495
|
+
<p class="subtitle">Pinged successfully.</p>
|
|
496
|
+
|
|
497
|
+
<div class="data-row">
|
|
498
|
+
<p class="data-label">Client</p>
|
|
499
|
+
<p class="data-value client">{{{{client}}}}</p>
|
|
500
|
+
</div>
|
|
501
|
+
|
|
502
|
+
<div class="data-row">
|
|
503
|
+
<p class="data-label">Timestamp</p>
|
|
504
|
+
<p class="data-value timestamp">{{{{ts}}}}</p>
|
|
505
|
+
</div>
|
|
506
|
+
|
|
507
|
+
<div class="data-row">
|
|
508
|
+
<p class="data-label">Data</p>
|
|
509
|
+
<p class="data-value">{{{{data}}}}</p>
|
|
510
|
+
</div>
|
|
511
|
+
|
|
512
|
+
<div class="data-row">
|
|
513
|
+
<p class="data-label">Operation ID</p>
|
|
514
|
+
<p class="data-value operation-id truncated">{{{{operation_id}}}}</p>
|
|
515
|
+
</div>
|
|
516
|
+
|
|
517
|
+
<button id="send-request-btn" class="api-button">Ping again</button>
|
|
518
|
+
</div>
|
|
519
|
+
|
|
520
|
+
<script>
|
|
521
|
+
document.getElementById('send-request-btn').addEventListener('click', () => {{
|
|
522
|
+
const apiEndpoint = 'https://neuronum.net/api/activate/{txID}';
|
|
523
|
+
|
|
524
|
+
const dataToSend = {{
|
|
525
|
+
"data": {{"ping": "node"}},
|
|
526
|
+
"cell": {{
|
|
527
|
+
"host": CLIENT_CELL,
|
|
528
|
+
"session": CLIENT_SESSION,
|
|
529
|
+
}}
|
|
530
|
+
}};
|
|
531
|
+
|
|
532
|
+
fetch(apiEndpoint, {{
|
|
533
|
+
method: 'POST',
|
|
534
|
+
headers: {{
|
|
535
|
+
'Content-Type': 'application/json',
|
|
536
|
+
'Accept': 'application/json'
|
|
537
|
+
}},
|
|
538
|
+
body: JSON.stringify(dataToSend)
|
|
539
|
+
}})
|
|
540
|
+
.then(response => {{
|
|
541
|
+
if (!response.ok) {{
|
|
542
|
+
throw new Error(`HTTP error! status: ${{response.status}}`);
|
|
543
|
+
}}
|
|
544
|
+
return response.json();
|
|
545
|
+
}})
|
|
546
|
+
.then(data => {{
|
|
547
|
+
if (data.success && data.response && data.response.html) {{
|
|
548
|
+
document.open();
|
|
549
|
+
document.write(data.response.html);
|
|
550
|
+
document.close();
|
|
551
|
+
console.log('API Response: Page replaced with new HTML.');
|
|
552
|
+
}} else {{
|
|
553
|
+
console.error('API Response does not contain HTML to replace the page:', data);
|
|
554
|
+
alert('API response error: Expected HTML content to replace the page.');
|
|
555
|
+
}}
|
|
556
|
+
}})
|
|
557
|
+
.catch(error => {{
|
|
558
|
+
console.error('API request failed:', error);
|
|
559
|
+
alert('API request failed. See the console for details.');
|
|
560
|
+
}});
|
|
561
|
+
}});
|
|
562
|
+
</script>
|
|
563
|
+
|
|
564
|
+
<div id="legal-banner" style="border-radius: 10px; margin: 15px; position: fixed; bottom: 0; left: 0; right: 0; background-color: #2a2a2a; color: #e0e0e0; padding: 16px; text-align: center; font-size: 14px; z-index: 9999; box-shadow: 0 -2px 10px rgba(0,0,0,0.5);">
|
|
565
|
+
By continuing, you agree to our
|
|
566
|
+
Terms (<span style="color: #8cafff;">{{{{terms_url}}}}</span>) &
|
|
567
|
+
Privacy Policy (<span style="color: #8cafff;">{{{{privacy_url}}}}</span>)
|
|
568
|
+
<br>
|
|
569
|
+
<button id="accept-legal" style="margin-top: 15px; margin-bottom: 15px; background: #01c07d; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer;">Accept</button>
|
|
570
|
+
<br>
|
|
571
|
+
Last Update: {{{{last_update}}}}
|
|
572
|
+
</div>
|
|
573
|
+
|
|
574
|
+
<script>
|
|
575
|
+
const banner = document.getElementById('legal-banner');
|
|
576
|
+
const acceptBtn = document.getElementById('accept-legal');
|
|
577
|
+
acceptBtn.addEventListener('click', () => {{
|
|
578
|
+
banner.remove();
|
|
579
|
+
}});
|
|
580
|
+
</script>
|
|
581
|
+
|
|
582
|
+
</body>
|
|
583
|
+
</html>
|
|
584
|
+
"""
|
|
585
|
+
html_path.write_text(html_content)
|
|
586
|
+
|
|
587
|
+
config_path = project_path / "config.json"
|
|
588
|
+
await asyncio.to_thread(
|
|
589
|
+
config_path.write_text,
|
|
590
|
+
f"""{{
|
|
591
|
+
"app_metadata": {{
|
|
592
|
+
"name": "{descr}",
|
|
593
|
+
"version": "1.0.0",
|
|
594
|
+
"author": "{host}"
|
|
595
|
+
}},
|
|
596
|
+
"data_gateways": [
|
|
597
|
+
{{
|
|
598
|
+
"type": "transmitter",
|
|
599
|
+
"id": "{txID}",
|
|
600
|
+
"info": "Ping Your Node"
|
|
601
|
+
}}
|
|
602
|
+
],
|
|
603
|
+
"legals": {{
|
|
604
|
+
"terms": "https://url_to_your/terms",
|
|
605
|
+
"privacy_policy": "https://url_to_your/privacy_policy",
|
|
606
|
+
"last_update" : "DD/MM/YYYY"
|
|
607
|
+
}}
|
|
608
|
+
}}"""
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
nodemd_path = project_path / "NODE.md"
|
|
612
|
+
await asyncio.to_thread(nodemd_path.write_text, f"""### NODE.md of {nodeID}
|
|
613
|
+
|
|
614
|
+
Welcome to your Node's documentation! This guide provides several ways for users to interact with your application.
|
|
327
615
|
|
|
328
|
-
|
|
329
|
-
|
|
616
|
+
***
|
|
617
|
+
|
|
618
|
+
### 💻 Using the CLI
|
|
619
|
+
|
|
620
|
+
To ping this Node via the command-line interface, use the following command:
|
|
621
|
+
|
|
622
|
+
`neuronum activate --tx {txID} 'ping:node'`
|
|
623
|
+
|
|
624
|
+
***
|
|
625
|
+
|
|
626
|
+
### 🐍 With Python
|
|
627
|
+
|
|
628
|
+
For programmatic access, use the following Python code snippet. This script utilizes the `neuronum` library to activate the transaction and receive a response.
|
|
629
|
+
|
|
630
|
+
```python
|
|
631
|
+
import asyncio
|
|
632
|
+
import neuronum
|
|
633
|
+
|
|
634
|
+
# Set up Cell connection parameters
|
|
635
|
+
cell = neuronum.Cell(
|
|
636
|
+
host="host", # Cell host
|
|
637
|
+
password="password", # Cell password
|
|
638
|
+
network="neuronum.net", # Cell network
|
|
639
|
+
synapse="synapse" # Cell synapse
|
|
640
|
+
)
|
|
641
|
+
|
|
642
|
+
async def main():
|
|
643
|
+
# Define the transaction ID and data payload
|
|
644
|
+
TX = "{txID}"
|
|
645
|
+
data = {{"ping": "node"}}
|
|
646
|
+
|
|
647
|
+
# Activate the transaction and get the response
|
|
648
|
+
tx_response = await cell.activate_tx(TX, data)
|
|
649
|
+
|
|
650
|
+
# Print the response from the Node
|
|
651
|
+
print(tx_response)
|
|
652
|
+
|
|
653
|
+
# Run the main asynchronous function
|
|
654
|
+
if __name__ == "__main__":
|
|
655
|
+
asyncio.run(main())
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
🤖 Via Cellai (Android App - Currently in Testing)
|
|
659
|
+
Download the app from the Google Play Store.
|
|
660
|
+
Send the command "Ping Node" to Cellai
|
|
661
|
+
""")
|
|
662
|
+
|
|
663
|
+
else:
|
|
664
|
+
stxID = "id::stx"
|
|
665
|
+
txID = "id::tx"
|
|
666
|
+
|
|
667
|
+
app_path = project_path / "app.py"
|
|
668
|
+
app_path.write_text(f"""\
|
|
330
669
|
import asyncio
|
|
331
670
|
import neuronum
|
|
332
671
|
import os
|
|
@@ -385,8 +724,8 @@ async def main():
|
|
|
385
724
|
asyncio.run(main())
|
|
386
725
|
""")
|
|
387
726
|
|
|
388
|
-
|
|
389
|
-
|
|
727
|
+
html_path = project_path / "ping.html"
|
|
728
|
+
html_content = f"""\
|
|
390
729
|
<!DOCTYPE html>
|
|
391
730
|
<html>
|
|
392
731
|
<head>
|
|
@@ -580,11 +919,11 @@ asyncio.run(main())
|
|
|
580
919
|
</body>
|
|
581
920
|
</html>
|
|
582
921
|
"""
|
|
583
|
-
|
|
922
|
+
html_path.write_text(html_content)
|
|
584
923
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
924
|
+
config_path = project_path / "config.json"
|
|
925
|
+
await asyncio.to_thread(
|
|
926
|
+
config_path.write_text,
|
|
588
927
|
f"""{{
|
|
589
928
|
"app_metadata": {{
|
|
590
929
|
"name": "{descr}",
|
|
@@ -606,8 +945,8 @@ f"""{{
|
|
|
606
945
|
}}"""
|
|
607
946
|
)
|
|
608
947
|
|
|
609
|
-
|
|
610
|
-
|
|
948
|
+
nodemd_path = project_path / "NODE.md"
|
|
949
|
+
await asyncio.to_thread(nodemd_path.write_text, f"""### NODE.md of {nodeID}
|
|
611
950
|
|
|
612
951
|
Welcome to your Node's documentation! This guide provides several ways for users to interact with your application.
|
|
613
952
|
|
|
@@ -664,7 +1003,7 @@ Send the command "Ping Node" to Cellai
|
|
|
664
1003
|
@click.command()
|
|
665
1004
|
@click.option('--d', is_flag=True, help="Start node in detached mode")
|
|
666
1005
|
def start_node(d):
|
|
667
|
-
|
|
1006
|
+
update_node_at_start()
|
|
668
1007
|
pid_file = Path.cwd() / "status.txt"
|
|
669
1008
|
system_name = platform.system()
|
|
670
1009
|
active_pids = []
|
|
@@ -695,7 +1034,7 @@ def start_node(d):
|
|
|
695
1034
|
click.echo("Starting Node...")
|
|
696
1035
|
|
|
697
1036
|
project_path = Path.cwd()
|
|
698
|
-
script_files = glob.glob("
|
|
1037
|
+
script_files = glob.glob("app.py")
|
|
699
1038
|
processes = []
|
|
700
1039
|
|
|
701
1040
|
for script in script_files:
|
|
@@ -792,7 +1131,7 @@ def check_node():
|
|
|
792
1131
|
@click.command()
|
|
793
1132
|
@click.option('--d', is_flag=True, help="Restart node in detached mode")
|
|
794
1133
|
def restart_node(d):
|
|
795
|
-
|
|
1134
|
+
update_node_at_start()
|
|
796
1135
|
pid_file = Path.cwd() / "status.txt"
|
|
797
1136
|
system_name = platform.system()
|
|
798
1137
|
|
|
@@ -842,7 +1181,7 @@ def restart_node(d):
|
|
|
842
1181
|
|
|
843
1182
|
click.echo(f"Starting Node {nodeID}...")
|
|
844
1183
|
project_path = Path.cwd()
|
|
845
|
-
script_files = glob.glob("
|
|
1184
|
+
script_files = glob.glob("app.py")
|
|
846
1185
|
processes = []
|
|
847
1186
|
|
|
848
1187
|
for script in script_files:
|
|
@@ -923,6 +1262,7 @@ async def async_stop_node():
|
|
|
923
1262
|
click.echo("Error: Unable to stop some node processes.")
|
|
924
1263
|
|
|
925
1264
|
|
|
1265
|
+
@click.command()
|
|
926
1266
|
def update_node():
|
|
927
1267
|
click.echo("Update your Node")
|
|
928
1268
|
env_data = {}
|
|
@@ -1042,6 +1382,125 @@ async def async_update_node(node_type: str, descr: str, partners:str) -> None:
|
|
|
1042
1382
|
click.echo(f"Neuronum Node '{nodeID}' updated!")
|
|
1043
1383
|
|
|
1044
1384
|
|
|
1385
|
+
def update_node_at_start():
|
|
1386
|
+
click.echo("Update your Node")
|
|
1387
|
+
env_data = {}
|
|
1388
|
+
|
|
1389
|
+
try:
|
|
1390
|
+
with open(".env", "r") as f:
|
|
1391
|
+
for line in f:
|
|
1392
|
+
key, value = line.strip().split("=")
|
|
1393
|
+
env_data[key] = value
|
|
1394
|
+
|
|
1395
|
+
host = env_data.get("HOST", "")
|
|
1396
|
+
|
|
1397
|
+
except FileNotFoundError:
|
|
1398
|
+
click.echo("Error: .env with credentials not found")
|
|
1399
|
+
return
|
|
1400
|
+
except Exception as e:
|
|
1401
|
+
click.echo(f"Error reading .env file: {e}")
|
|
1402
|
+
return
|
|
1403
|
+
|
|
1404
|
+
if host.startswith("CMTY_"):
|
|
1405
|
+
node_type = questionary.select(
|
|
1406
|
+
"Community Cells can only create private Nodes",
|
|
1407
|
+
choices=["private"]
|
|
1408
|
+
).ask()
|
|
1409
|
+
else:
|
|
1410
|
+
node_type = questionary.select(
|
|
1411
|
+
"Who can view your Node?:",
|
|
1412
|
+
choices=["public", "private", "partners"]
|
|
1413
|
+
).ask()
|
|
1414
|
+
partners = "None"
|
|
1415
|
+
if node_type == "partners":
|
|
1416
|
+
prompt_msg = (
|
|
1417
|
+
"Enter the list of partners who can view this Node.\n"
|
|
1418
|
+
"Format: partner::cell, partner::cell, partner::cell\n"
|
|
1419
|
+
"Press Enter to leave the list unchanged"
|
|
1420
|
+
)
|
|
1421
|
+
partners = click.prompt(
|
|
1422
|
+
prompt_msg,
|
|
1423
|
+
default="None",
|
|
1424
|
+
show_default=False
|
|
1425
|
+
).strip()
|
|
1426
|
+
descr = click.prompt(
|
|
1427
|
+
"Update Node description: Type up to 25 characters, or press Enter to leave it unchanged",
|
|
1428
|
+
default="None",
|
|
1429
|
+
show_default=False
|
|
1430
|
+
).strip()
|
|
1431
|
+
if descr and len(descr) > 25:
|
|
1432
|
+
click.echo("Description too long. Max 25 characters allowed.")
|
|
1433
|
+
return
|
|
1434
|
+
asyncio.run(async_update_node_at_start(node_type, descr, partners))
|
|
1435
|
+
|
|
1436
|
+
async def async_update_node_at_start(node_type: str, descr: str, partners:str) -> None:
|
|
1437
|
+
env_data = {}
|
|
1438
|
+
|
|
1439
|
+
try:
|
|
1440
|
+
with open(".env", "r") as f:
|
|
1441
|
+
for line in f:
|
|
1442
|
+
key, value = line.strip().split("=")
|
|
1443
|
+
env_data[key] = value
|
|
1444
|
+
|
|
1445
|
+
nodeID = env_data.get("NODE", "")
|
|
1446
|
+
host = env_data.get("HOST", "")
|
|
1447
|
+
password = env_data.get("PASSWORD", "")
|
|
1448
|
+
network = env_data.get("NETWORK", "")
|
|
1449
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
1450
|
+
|
|
1451
|
+
except FileNotFoundError:
|
|
1452
|
+
click.echo("Error: .env with credentials not found")
|
|
1453
|
+
return
|
|
1454
|
+
except Exception as e:
|
|
1455
|
+
click.echo(f"Error reading .env file: {e}")
|
|
1456
|
+
return
|
|
1457
|
+
|
|
1458
|
+
try:
|
|
1459
|
+
with open("NODE.md", "r") as f:
|
|
1460
|
+
nodemd_file = f.read()
|
|
1461
|
+
|
|
1462
|
+
with open("config.json", "r") as f:
|
|
1463
|
+
config_file = f.read()
|
|
1464
|
+
|
|
1465
|
+
except FileNotFoundError:
|
|
1466
|
+
click.echo("Error: NODE.md file not found")
|
|
1467
|
+
return
|
|
1468
|
+
except Exception as e:
|
|
1469
|
+
click.echo(f"Error reading NODE.md file: {e}")
|
|
1470
|
+
return
|
|
1471
|
+
|
|
1472
|
+
if node_type == "partners":
|
|
1473
|
+
node_type = partners
|
|
1474
|
+
|
|
1475
|
+
url = f"https://{network}/api/update_node"
|
|
1476
|
+
node = {
|
|
1477
|
+
"nodeID": nodeID,
|
|
1478
|
+
"host": host,
|
|
1479
|
+
"password": password,
|
|
1480
|
+
"synapse": synapse,
|
|
1481
|
+
"node_type": node_type,
|
|
1482
|
+
"nodemd_file": nodemd_file,
|
|
1483
|
+
"config_file": config_file,
|
|
1484
|
+
"descr": descr,
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
async with aiohttp.ClientSession() as session:
|
|
1488
|
+
try:
|
|
1489
|
+
async with session.post(url, json=node) as response:
|
|
1490
|
+
response.raise_for_status()
|
|
1491
|
+
data = await response.json()
|
|
1492
|
+
nodeID = data["nodeID"]
|
|
1493
|
+
node_url = data["node_url"]
|
|
1494
|
+
except aiohttp.ClientError as e:
|
|
1495
|
+
click.echo(f"Error sending request: {e}")
|
|
1496
|
+
return
|
|
1497
|
+
|
|
1498
|
+
if node_type == "public":
|
|
1499
|
+
click.echo(f"Neuronum Node '{nodeID}' updated! Visit: {node_url}")
|
|
1500
|
+
else:
|
|
1501
|
+
click.echo(f"Neuronum Node '{nodeID}' updated!")
|
|
1502
|
+
|
|
1503
|
+
|
|
1045
1504
|
@click.command()
|
|
1046
1505
|
def delete_node():
|
|
1047
1506
|
asyncio.run(async_delete_node())
|
|
@@ -1219,6 +1678,7 @@ cli.add_command(view_cell)
|
|
|
1219
1678
|
cli.add_command(disconnect_cell)
|
|
1220
1679
|
cli.add_command(delete_cell)
|
|
1221
1680
|
cli.add_command(init_node)
|
|
1681
|
+
cli.add_command(update_node)
|
|
1222
1682
|
cli.add_command(start_node)
|
|
1223
1683
|
cli.add_command(restart_node)
|
|
1224
1684
|
cli.add_command(stop_node)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuronum
|
|
3
|
-
Version: 7.0.
|
|
3
|
+
Version: 7.0.4
|
|
4
4
|
Summary: Official client library to interact with the Neuronum Network
|
|
5
5
|
Home-page: https://neuronum.net
|
|
6
6
|
Author: Neuronum Cybernetics
|
|
@@ -128,7 +128,7 @@ ping.html: A static HTML file used to render web-based responses.
|
|
|
128
128
|
|
|
129
129
|
Change into Node folder
|
|
130
130
|
```sh
|
|
131
|
-
cd
|
|
131
|
+
cd Test App_<your_node_id>
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
Start your Node:
|
|
@@ -154,7 +154,7 @@ cell = neuronum.Cell( # set Cell connection
|
|
|
154
154
|
async def main():
|
|
155
155
|
|
|
156
156
|
TX = "id::tx" # select the Transmitter TX
|
|
157
|
-
data = {"
|
|
157
|
+
data = {"ping": "node"}
|
|
158
158
|
tx_response = await cell.activate_tx(TX, data) # activate TX - > get response back
|
|
159
159
|
print(tx_response) # print tx response
|
|
160
160
|
|
|
@@ -163,7 +163,7 @@ asyncio.run(main())
|
|
|
163
163
|
|
|
164
164
|
#### **CLI-based**
|
|
165
165
|
```sh
|
|
166
|
-
neuronum activate --tx id::tx '
|
|
166
|
+
neuronum activate --tx id::tx 'ping:node'
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
#### **Cellai (in Testing)**
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
cli/main.py,sha256=oj3_-lFGFUlCNlZoKmKK2b9yIvAd6KdXCFNMdNc6fZo,51733
|
|
3
|
+
neuronum/__init__.py,sha256=tAdqNC9rByY_CwG63yAyEe34phBdQ_Vv3FyFpTXQ2wo,45
|
|
4
|
+
neuronum/neuronum.py,sha256=5OjJIAmY7haT6eJ3P767RFk-LTvNFRrlkjB9mOozgN8,17971
|
|
5
|
+
neuronum-7.0.4.dist-info/licenses/LICENSE.md,sha256=m7pw_FktMNCs4tcy2UXP3QQP2S_je28P1SepdYoo0Xo,1961
|
|
6
|
+
neuronum-7.0.4.dist-info/METADATA,sha256=QoAgYz-i7_mhznemchEjnTGI2l2y-Z36ZCZGebPluzM,5871
|
|
7
|
+
neuronum-7.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
+
neuronum-7.0.4.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
|
|
9
|
+
neuronum-7.0.4.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
|
|
10
|
+
neuronum-7.0.4.dist-info/RECORD,,
|
neuronum-7.0.2.dist-info/RECORD
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
cli/main.py,sha256=jaRDzs_SRdr_2pkdUntg9IBNKfl5_TMB-RQJbgQMPZc,37766
|
|
3
|
-
neuronum/__init__.py,sha256=tAdqNC9rByY_CwG63yAyEe34phBdQ_Vv3FyFpTXQ2wo,45
|
|
4
|
-
neuronum/neuronum.py,sha256=5OjJIAmY7haT6eJ3P767RFk-LTvNFRrlkjB9mOozgN8,17971
|
|
5
|
-
neuronum-7.0.2.dist-info/licenses/LICENSE.md,sha256=m7pw_FktMNCs4tcy2UXP3QQP2S_je28P1SepdYoo0Xo,1961
|
|
6
|
-
neuronum-7.0.2.dist-info/METADATA,sha256=rjaMl_SCEQfxY7dTMnyuv4WxybF7mJqwQOpTddskqo0,5902
|
|
7
|
-
neuronum-7.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
-
neuronum-7.0.2.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
|
|
9
|
-
neuronum-7.0.2.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
|
|
10
|
-
neuronum-7.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|