neuronum 8.1.0__tar.gz → 8.3.0__tar.gz
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.
- {neuronum-8.1.0 → neuronum-8.3.0}/PKG-INFO +1 -1
- {neuronum-8.1.0 → neuronum-8.3.0}/cli/main.py +81 -166
- {neuronum-8.1.0 → neuronum-8.3.0}/neuronum/neuronum.py +3 -5
- {neuronum-8.1.0 → neuronum-8.3.0}/neuronum.egg-info/PKG-INFO +1 -1
- {neuronum-8.1.0 → neuronum-8.3.0}/setup.py +1 -1
- {neuronum-8.1.0 → neuronum-8.3.0}/LICENSE.md +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/README.md +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/cli/__init__.py +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/neuronum/__init__.py +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/neuronum.egg-info/SOURCES.txt +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/neuronum.egg-info/dependency_links.txt +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/neuronum.egg-info/entry_points.txt +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/neuronum.egg-info/requires.txt +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/neuronum.egg-info/top_level.txt +0 -0
- {neuronum-8.1.0 → neuronum-8.3.0}/setup.cfg +0 -0
|
@@ -534,7 +534,9 @@ f"""{{
|
|
|
534
534
|
"app_metadata": {{
|
|
535
535
|
"name": "{descr}",
|
|
536
536
|
"version": "1.0.0",
|
|
537
|
-
"author": "{host}"
|
|
537
|
+
"author": "{host}",
|
|
538
|
+
"audience": "private",
|
|
539
|
+
"logo": "https://neuronum.net/static/logo.png"
|
|
538
540
|
}},
|
|
539
541
|
"data_gateways": [
|
|
540
542
|
{{
|
|
@@ -815,107 +817,72 @@ async def async_stop_node():
|
|
|
815
817
|
@click.command()
|
|
816
818
|
def update_node():
|
|
817
819
|
click.echo("Update your Node")
|
|
818
|
-
credentials_folder_path = Path.home() / ".neuronum"
|
|
819
|
-
env_path = credentials_folder_path / ".env"
|
|
820
|
-
env_data = {}
|
|
821
|
-
|
|
822
820
|
try:
|
|
821
|
+
env_path = Path.home() / ".neuronum" / ".env"
|
|
822
|
+
env_data = {}
|
|
823
823
|
with open(env_path, "r") as f:
|
|
824
824
|
for line in f:
|
|
825
|
-
|
|
826
|
-
|
|
825
|
+
if "=" in line:
|
|
826
|
+
key, value = line.strip().split("=", 1)
|
|
827
|
+
env_data[key] = value
|
|
827
828
|
|
|
828
829
|
host = env_data.get("HOST", "")
|
|
829
830
|
|
|
830
|
-
|
|
831
|
-
|
|
831
|
+
with open("config.json", "r") as f:
|
|
832
|
+
config_data = json.load(f)
|
|
833
|
+
|
|
834
|
+
audience = config_data.get("app_metadata", {}).get("audience", "")
|
|
835
|
+
descr = config_data.get("app_metadata", {}).get("name", "")
|
|
836
|
+
|
|
837
|
+
if host.startswith("CMTY_") and audience != "private":
|
|
838
|
+
raise click.ClickException(
|
|
839
|
+
'Community Cells can only create private Nodes. Set audience to "private".'
|
|
840
|
+
)
|
|
841
|
+
if descr and len(descr) > 25:
|
|
842
|
+
raise click.ClickException(
|
|
843
|
+
'Description too long. Max 25 characters allowed.'
|
|
844
|
+
)
|
|
845
|
+
|
|
846
|
+
except FileNotFoundError as e:
|
|
847
|
+
click.echo(f"Error: File not found - {e.filename}")
|
|
832
848
|
return
|
|
833
|
-
except
|
|
834
|
-
click.echo(
|
|
849
|
+
except click.ClickException as e:
|
|
850
|
+
click.echo(e.format_message())
|
|
835
851
|
return
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
node_type = questionary.select(
|
|
839
|
-
"Community Cells can only create private Nodes",
|
|
840
|
-
choices=["private"]
|
|
841
|
-
).ask()
|
|
842
|
-
else:
|
|
843
|
-
node_type = questionary.select(
|
|
844
|
-
"Who can view your Node?:",
|
|
845
|
-
choices=["public", "private", "partners"]
|
|
846
|
-
).ask()
|
|
847
|
-
partners = "None"
|
|
848
|
-
if node_type == "partners":
|
|
849
|
-
prompt_msg = (
|
|
850
|
-
"Enter the list of partners who can view this Node.\n"
|
|
851
|
-
"Format: partner::cell, partner::cell, partner::cell\n"
|
|
852
|
-
"Press Enter to leave the list unchanged"
|
|
853
|
-
)
|
|
854
|
-
partners = click.prompt(
|
|
855
|
-
prompt_msg,
|
|
856
|
-
default="None",
|
|
857
|
-
show_default=False
|
|
858
|
-
).strip()
|
|
859
|
-
descr = click.prompt(
|
|
860
|
-
"Update Node description: Type up to 25 characters, or press Enter to leave it unchanged",
|
|
861
|
-
default="None",
|
|
862
|
-
show_default=False
|
|
863
|
-
).strip()
|
|
864
|
-
if descr and len(descr) > 25:
|
|
865
|
-
click.echo("Description too long. Max 25 characters allowed.")
|
|
852
|
+
except Exception as e:
|
|
853
|
+
click.echo(f"Error reading files: {e}")
|
|
866
854
|
return
|
|
867
|
-
asyncio.run(async_update_node(node_type, descr, partners))
|
|
868
855
|
|
|
869
|
-
|
|
870
|
-
credentials_folder_path = Path.home() / ".neuronum"
|
|
871
|
-
env_path = credentials_folder_path / ".env"
|
|
872
|
-
env_data = {}
|
|
856
|
+
asyncio.run(async_update_node(env_data, config_data, audience, descr))
|
|
873
857
|
|
|
874
|
-
try:
|
|
875
|
-
with open(env_path, "r") as f:
|
|
876
|
-
for line in f:
|
|
877
|
-
key, value = line.strip().split("=")
|
|
878
|
-
env_data[key] = value
|
|
879
858
|
|
|
859
|
+
async def async_update_node(env_data, config_data, audience: str, descr: str):
|
|
860
|
+
try:
|
|
880
861
|
host = env_data.get("HOST", "")
|
|
881
862
|
password = env_data.get("PASSWORD", "")
|
|
882
863
|
network = env_data.get("NETWORK", "")
|
|
883
864
|
synapse = env_data.get("SYNAPSE", "")
|
|
884
865
|
|
|
885
|
-
|
|
886
|
-
data = json.load(f)
|
|
887
|
-
|
|
888
|
-
nodeID = data['data_gateways'][0]['node_id']
|
|
889
|
-
|
|
890
|
-
except FileNotFoundError:
|
|
891
|
-
click.echo("Error: .env with credentials not found")
|
|
892
|
-
return
|
|
893
|
-
except Exception as e:
|
|
894
|
-
click.echo(f"Error reading .env file: {e}")
|
|
895
|
-
return
|
|
866
|
+
node_id = config_data.get("data_gateways", [{}])[0].get("node_id", "")
|
|
896
867
|
|
|
897
|
-
try:
|
|
898
868
|
with open("config.json", "r") as f:
|
|
899
|
-
|
|
869
|
+
config_file_content = f.read()
|
|
900
870
|
|
|
901
871
|
except FileNotFoundError:
|
|
902
|
-
click.echo("Error:
|
|
872
|
+
click.echo("Error: config.json or .env not found")
|
|
903
873
|
return
|
|
904
874
|
except Exception as e:
|
|
905
|
-
click.echo(f"Error reading
|
|
875
|
+
click.echo(f"Error reading files: {e}")
|
|
906
876
|
return
|
|
907
|
-
|
|
908
|
-
if node_type == "partners":
|
|
909
|
-
node_type = partners
|
|
910
877
|
|
|
911
878
|
url = f"https://{network}/api/update_node"
|
|
912
879
|
node = {
|
|
913
|
-
"nodeID":
|
|
880
|
+
"nodeID": node_id,
|
|
914
881
|
"host": host,
|
|
915
882
|
"password": password,
|
|
916
883
|
"synapse": synapse,
|
|
917
|
-
"node_type":
|
|
918
|
-
"config_file":
|
|
884
|
+
"node_type": audience,
|
|
885
|
+
"config_file": config_file_content,
|
|
919
886
|
"descr": descr,
|
|
920
887
|
}
|
|
921
888
|
|
|
@@ -924,120 +891,73 @@ async def async_update_node(node_type: str, descr: str, partners:str) -> None:
|
|
|
924
891
|
async with session.post(url, json=node) as response:
|
|
925
892
|
response.raise_for_status()
|
|
926
893
|
data = await response.json()
|
|
927
|
-
|
|
894
|
+
updated_node_id = data.get("nodeID", node_id)
|
|
895
|
+
click.echo(f"Neuronum Node '{updated_node_id}' updated!")
|
|
928
896
|
except aiohttp.ClientError as e:
|
|
929
897
|
click.echo(f"Error sending request: {e}")
|
|
930
|
-
return
|
|
931
898
|
|
|
932
|
-
if node_type == "public":
|
|
933
|
-
click.echo(f"Neuronum Node '{nodeID}' updated!")
|
|
934
|
-
else:
|
|
935
|
-
click.echo(f"Neuronum Node '{nodeID}' updated!")
|
|
936
899
|
|
|
937
900
|
|
|
938
901
|
def update_node_at_start():
|
|
939
902
|
click.echo("Update your Node")
|
|
940
|
-
credentials_folder_path = Path.home() / ".neuronum"
|
|
941
|
-
env_path = credentials_folder_path / ".env"
|
|
942
|
-
env_data = {}
|
|
943
|
-
|
|
944
903
|
try:
|
|
904
|
+
env_path = Path.home() / ".neuronum" / ".env"
|
|
905
|
+
env_data = {}
|
|
945
906
|
with open(env_path, "r") as f:
|
|
946
907
|
for line in f:
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
host = env_data.get("HOST", "")
|
|
951
|
-
|
|
952
|
-
except FileNotFoundError:
|
|
953
|
-
click.echo("Error: .env with credentials not found")
|
|
954
|
-
return
|
|
955
|
-
except Exception as e:
|
|
956
|
-
click.echo(f"Error reading .env file: {e}")
|
|
957
|
-
return
|
|
958
|
-
|
|
959
|
-
if host.startswith("CMTY_"):
|
|
960
|
-
node_type = questionary.select(
|
|
961
|
-
"Community Cells can only create private Nodes",
|
|
962
|
-
choices=["private"]
|
|
963
|
-
).ask()
|
|
964
|
-
else:
|
|
965
|
-
node_type = questionary.select(
|
|
966
|
-
"Who can view your Node?:",
|
|
967
|
-
choices=["public", "private", "partners"]
|
|
968
|
-
).ask()
|
|
969
|
-
partners = "None"
|
|
970
|
-
if node_type == "partners":
|
|
971
|
-
prompt_msg = (
|
|
972
|
-
"Enter the list of partners who can view this Node.\n"
|
|
973
|
-
"Format: partner::cell, partner::cell, partner::cell\n"
|
|
974
|
-
"Press Enter to leave the list unchanged"
|
|
975
|
-
)
|
|
976
|
-
partners = click.prompt(
|
|
977
|
-
prompt_msg,
|
|
978
|
-
default="None",
|
|
979
|
-
show_default=False
|
|
980
|
-
).strip()
|
|
981
|
-
descr = click.prompt(
|
|
982
|
-
"Update Node description: Type up to 25 characters, or press Enter to leave it unchanged",
|
|
983
|
-
default="None",
|
|
984
|
-
show_default=False
|
|
985
|
-
).strip()
|
|
986
|
-
if descr and len(descr) > 25:
|
|
987
|
-
click.echo("Description too long. Max 25 characters allowed.")
|
|
988
|
-
return
|
|
989
|
-
asyncio.run(async_update_node_at_start(node_type, descr, partners))
|
|
990
|
-
|
|
991
|
-
async def async_update_node_at_start(node_type: str, descr: str, partners:str) -> None:
|
|
992
|
-
credentials_folder_path = Path.home() / ".neuronum"
|
|
993
|
-
env_path = credentials_folder_path / ".env"
|
|
994
|
-
env_data = {}
|
|
908
|
+
if "=" in line:
|
|
909
|
+
key, value = line.strip().split("=", 1)
|
|
910
|
+
env_data[key] = value
|
|
995
911
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
for line in f:
|
|
999
|
-
key, value = line.strip().split("=")
|
|
1000
|
-
env_data[key] = value
|
|
912
|
+
with open("config.json", "r") as f:
|
|
913
|
+
config_data = json.load(f)
|
|
1001
914
|
|
|
1002
915
|
host = env_data.get("HOST", "")
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
916
|
+
audience = config_data.get("app_metadata", {}).get("audience", "")
|
|
917
|
+
descr = config_data.get("app_metadata", {}).get("name", "")
|
|
918
|
+
|
|
919
|
+
if host.startswith("CMTY_") and audience != "private":
|
|
920
|
+
raise click.ClickException(
|
|
921
|
+
'Community Cells can only start private Nodes. Node starting "privately".'
|
|
922
|
+
)
|
|
923
|
+
if descr and len(descr) > 25:
|
|
924
|
+
raise click.ClickException(
|
|
925
|
+
'Description too long. Max 25 characters allowed.'
|
|
926
|
+
)
|
|
927
|
+
|
|
928
|
+
asyncio.run(_async_update_node_at_start(env_data, config_data, audience, descr))
|
|
929
|
+
|
|
930
|
+
except FileNotFoundError as e:
|
|
931
|
+
click.echo(f"Error: File not found - {e.filename}")
|
|
932
|
+
except click.ClickException as e:
|
|
933
|
+
click.echo(e.format_message())
|
|
934
|
+
except Exception as e:
|
|
935
|
+
click.echo(f"Unexpected error: {e}")
|
|
1006
936
|
|
|
1007
|
-
with open('config.json', 'r') as f:
|
|
1008
|
-
data = json.load(f)
|
|
1009
937
|
|
|
1010
|
-
|
|
938
|
+
async def _async_update_node_at_start(env_data, config_data, audience, descr):
|
|
939
|
+
host = env_data.get("HOST", "")
|
|
940
|
+
password = env_data.get("PASSWORD", "")
|
|
941
|
+
network = env_data.get("NETWORK", "")
|
|
942
|
+
synapse = env_data.get("SYNAPSE", "")
|
|
1011
943
|
|
|
1012
|
-
|
|
1013
|
-
click.echo("Error: .env with credentials not found")
|
|
1014
|
-
return
|
|
1015
|
-
except Exception as e:
|
|
1016
|
-
click.echo(f"Error reading .env file: {e}")
|
|
1017
|
-
return
|
|
944
|
+
node_id = config_data.get("data_gateways", [{}])[0].get("node_id", "")
|
|
1018
945
|
|
|
1019
946
|
try:
|
|
1020
947
|
with open("config.json", "r") as f:
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
except FileNotFoundError:
|
|
1024
|
-
click.echo("Error: File not found")
|
|
1025
|
-
return
|
|
948
|
+
config_file_content = f.read()
|
|
1026
949
|
except Exception as e:
|
|
1027
|
-
click.echo(f"Error reading
|
|
950
|
+
click.echo(f"Error reading config.json content: {e}")
|
|
1028
951
|
return
|
|
1029
|
-
|
|
1030
|
-
if node_type == "partners":
|
|
1031
|
-
node_type = partners
|
|
1032
952
|
|
|
1033
953
|
url = f"https://{network}/api/update_node"
|
|
1034
954
|
node = {
|
|
1035
|
-
"nodeID":
|
|
955
|
+
"nodeID": node_id,
|
|
1036
956
|
"host": host,
|
|
1037
957
|
"password": password,
|
|
1038
958
|
"synapse": synapse,
|
|
1039
|
-
"node_type":
|
|
1040
|
-
"config_file":
|
|
959
|
+
"node_type": audience,
|
|
960
|
+
"config_file": config_file_content,
|
|
1041
961
|
"descr": descr,
|
|
1042
962
|
}
|
|
1043
963
|
|
|
@@ -1046,15 +966,10 @@ async def async_update_node_at_start(node_type: str, descr: str, partners:str) -
|
|
|
1046
966
|
async with session.post(url, json=node) as response:
|
|
1047
967
|
response.raise_for_status()
|
|
1048
968
|
data = await response.json()
|
|
1049
|
-
|
|
969
|
+
updated_node_id = data.get("nodeID", node_id)
|
|
970
|
+
click.echo(f"Neuronum Node '{updated_node_id}' updated!")
|
|
1050
971
|
except aiohttp.ClientError as e:
|
|
1051
972
|
click.echo(f"Error sending request: {e}")
|
|
1052
|
-
return
|
|
1053
|
-
|
|
1054
|
-
if node_type == "public":
|
|
1055
|
-
click.echo(f"Neuronum Node '{nodeID}' updated!")
|
|
1056
|
-
else:
|
|
1057
|
-
click.echo(f"Neuronum Node '{nodeID}' updated!")
|
|
1058
973
|
|
|
1059
974
|
|
|
1060
975
|
@click.command()
|
|
@@ -35,6 +35,7 @@ class Node:
|
|
|
35
35
|
"synapse": self.synapse
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
|
|
38
39
|
def _load_private_key(self):
|
|
39
40
|
try:
|
|
40
41
|
with open(self.private_key_path, "rb") as f:
|
|
@@ -43,12 +44,12 @@ class Node:
|
|
|
43
44
|
password=None,
|
|
44
45
|
backend=default_backend()
|
|
45
46
|
)
|
|
46
|
-
print("Private key loaded successfully.")
|
|
47
47
|
return private_key
|
|
48
48
|
except FileNotFoundError:
|
|
49
49
|
print(f"Private key file not found at {self.private_key_path}.")
|
|
50
50
|
return None
|
|
51
51
|
|
|
52
|
+
|
|
52
53
|
def _load_host(self):
|
|
53
54
|
credentials_folder_path = Path.home() / ".neuronum"
|
|
54
55
|
env_path = credentials_folder_path / ".env"
|
|
@@ -130,8 +131,6 @@ class Node:
|
|
|
130
131
|
f.read(),
|
|
131
132
|
backend=default_backend()
|
|
132
133
|
)
|
|
133
|
-
print("Public key loaded successfully.")
|
|
134
|
-
print(public_key)
|
|
135
134
|
return public_key
|
|
136
135
|
except FileNotFoundError:
|
|
137
136
|
print(f"Public key file not found at {self.public_key_path}. Deriving from private key.")
|
|
@@ -147,7 +146,6 @@ class Node:
|
|
|
147
146
|
print("Public key not loaded. Cannot generate JWK.")
|
|
148
147
|
return None
|
|
149
148
|
|
|
150
|
-
print("Public key loaded successfully.")
|
|
151
149
|
public_numbers = public_key.public_numbers()
|
|
152
150
|
|
|
153
151
|
x_bytes = public_numbers.x.to_bytes((public_numbers.x.bit_length() + 7) // 8, 'big')
|
|
@@ -196,7 +194,7 @@ class Node:
|
|
|
196
194
|
try:
|
|
197
195
|
async with websockets.connect(full_url) as ws:
|
|
198
196
|
await ws.send(json.dumps(auth_payload))
|
|
199
|
-
print("
|
|
197
|
+
print("Node syncing...")
|
|
200
198
|
while True:
|
|
201
199
|
try:
|
|
202
200
|
raw_operation = await ws.recv()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|