ns2 0.2.6__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.
Files changed (98) hide show
  1. ns2/__init__.py +0 -0
  2. ns2/core.py +0 -0
  3. ns2/dbus/__init__.py +0 -0
  4. ns2/dbus/dbus.py +13 -0
  5. ns2/lib/__init__.py +0 -0
  6. ns2/lib/accounts.py +130 -0
  7. ns2/lib/commands.py +32 -0
  8. ns2/lib/firewalld.py +167 -0
  9. ns2/lib/introspection/org.fedoraproject.FirewallD1.config.xml +3 -0
  10. ns2/lib/introspection/org.fedoraproject.FirewallD1.xml +763 -0
  11. ns2/lib/introspection/org.freedesktop.NetworkManager.AccessPoint.xml +106 -0
  12. ns2/lib/introspection/org.freedesktop.NetworkManager.AgentManager.xml +43 -0
  13. ns2/lib/introspection/org.freedesktop.NetworkManager.Checkpoint.xml +36 -0
  14. ns2/lib/introspection/org.freedesktop.NetworkManager.Connection.Active.xml +185 -0
  15. ns2/lib/introspection/org.freedesktop.NetworkManager.DHCP4Config.xml +21 -0
  16. ns2/lib/introspection/org.freedesktop.NetworkManager.DHCP6Config.xml +20 -0
  17. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Adsl.xml +21 -0
  18. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Bluetooth.xml +36 -0
  19. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Bond.xml +40 -0
  20. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Bridge.xml +41 -0
  21. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Dummy.xml +20 -0
  22. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Generic.xml +27 -0
  23. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Hsr.xml +51 -0
  24. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.IPTunnel.xml +107 -0
  25. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Infiniband.xml +31 -0
  26. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Ipvlan.xml +38 -0
  27. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Loopback.xml +8 -0
  28. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Lowpan.xml +27 -0
  29. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Macsec.xml +109 -0
  30. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Macvlan.xml +39 -0
  31. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Modem.xml +62 -0
  32. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.xml +34 -0
  33. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.OvsBridge.xml +21 -0
  34. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.OvsInterface.xml +11 -0
  35. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.OvsPort.xml +21 -0
  36. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Ppp.xml +11 -0
  37. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Statistics.xml +35 -0
  38. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Team.xml +48 -0
  39. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Tun.xml +65 -0
  40. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Veth.xml +18 -0
  41. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Vlan.xml +45 -0
  42. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Vrf.xml +18 -0
  43. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Vxlan.xml +139 -0
  44. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.WiMax.xml +109 -0
  45. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.WifiP2P.xml +76 -0
  46. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.WireGuard.xml +38 -0
  47. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Wired.xml +53 -0
  48. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Wireless.xml +131 -0
  49. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Wpan.xml +20 -0
  50. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.xml +407 -0
  51. ns2/lib/introspection/org.freedesktop.NetworkManager.DnsManager.xml +40 -0
  52. ns2/lib/introspection/org.freedesktop.NetworkManager.IP4Config.xml +125 -0
  53. ns2/lib/introspection/org.freedesktop.NetworkManager.IP6Config.xml +95 -0
  54. ns2/lib/introspection/org.freedesktop.NetworkManager.PPP.xml +34 -0
  55. ns2/lib/introspection/org.freedesktop.NetworkManager.SecretAgent.xml +94 -0
  56. ns2/lib/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml +224 -0
  57. ns2/lib/introspection/org.freedesktop.NetworkManager.Settings.xml +233 -0
  58. ns2/lib/introspection/org.freedesktop.NetworkManager.VPN.Connection.xml +42 -0
  59. ns2/lib/introspection/org.freedesktop.NetworkManager.VPN.Plugin.xml +204 -0
  60. ns2/lib/introspection/org.freedesktop.NetworkManager.WiMax.Nsp.xml +35 -0
  61. ns2/lib/introspection/org.freedesktop.NetworkManager.WifiP2PPeer.xml +91 -0
  62. ns2/lib/introspection/org.freedesktop.NetworkManager.xml +598 -0
  63. ns2/lib/lib.py +0 -0
  64. ns2/lib/network_delay.py +92 -0
  65. ns2/lib/networking.py +528 -0
  66. ns2/lib/ntl.py +188 -0
  67. ns2/lib/pam_client.py +37 -0
  68. ns2/lib/ping_data_collector.py +37 -0
  69. ns2/lib/snmp.py +511 -0
  70. ns2/lib/socket.py +132 -0
  71. ns2/lib/socket_client.py +62 -0
  72. ns2/lib/systemd.py +151 -0
  73. ns2/lib/test.py +374 -0
  74. ns2/lib/udp_client.py +227 -0
  75. ns2/lib/udp_server.py +167 -0
  76. ns2/snmp/__init__.py +0 -0
  77. ns2/snmp/ns_dbus_service.py +38 -0
  78. ns2/snmp/pam_interface.py +19 -0
  79. ns2/snmp/snmp_interface.py +66 -0
  80. ns2/ui/__init__.py +0 -0
  81. ns2/ui/assets/NOVUS_LOGO.svg +105 -0
  82. ns2/ui/assets/favicon.png +0 -0
  83. ns2/ui/firewalld_page.py +375 -0
  84. ns2/ui/fpga_page.py +24 -0
  85. ns2/ui/login.py +65 -0
  86. ns2/ui/main.py +200 -0
  87. ns2/ui/networking_page.py +406 -0
  88. ns2/ui/ntp.py +105 -0
  89. ns2/ui/root.py +31 -0
  90. ns2/ui/snmp_page.py +353 -0
  91. ns2/ui/terminal.py +65 -0
  92. ns2/ui/tests_page.py +116 -0
  93. ns2/ui/theme.py +25 -0
  94. ns2/utils.py +5 -0
  95. ns2-0.2.6.dist-info/METADATA +78 -0
  96. ns2-0.2.6.dist-info/RECORD +98 -0
  97. ns2-0.2.6.dist-info/WHEEL +4 -0
  98. ns2-0.2.6.dist-info/entry_points.txt +3 -0
ns2/lib/udp_client.py ADDED
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ UDP Hole Punching - Peer Client
4
+ This client registers with the rendezvous server and establishes P2P connections.
5
+ """
6
+
7
+ import socket
8
+ import threading
9
+ import json
10
+ import time
11
+ import sys
12
+
13
+ class PeerClient:
14
+ def __init__(self, peer_id, server_host, server_port=5000):
15
+ self.peer_id = peer_id
16
+ self.server_addr = (server_host, server_port)
17
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
18
+ self.sock.bind(('0.0.0.0', 0)) # Bind to any available port
19
+ self.local_port = self.sock.getsockname()[1]
20
+
21
+ self.connected_peers = {} # {peer_id: (ip, port)}
22
+ self.running = True
23
+
24
+ print(f"Peer '{peer_id}' started on local port {self.local_port}")
25
+
26
+ def register(self):
27
+ """Register with the rendezvous server"""
28
+ msg = {
29
+ 'cmd': 'register',
30
+ 'peer_id': self.peer_id
31
+ }
32
+ self.sock.sendto(json.dumps(msg).encode(), self.server_addr)
33
+ print(f"Registered with server at {self.server_addr}")
34
+
35
+ def send_heartbeat(self):
36
+ """Send periodic heartbeats to the server"""
37
+ while self.running:
38
+ try:
39
+ msg = {
40
+ 'cmd': 'heartbeat',
41
+ 'peer_id': self.peer_id
42
+ }
43
+ self.sock.sendto(json.dumps(msg).encode(), self.server_addr)
44
+ time.sleep(10)
45
+ except:
46
+ break
47
+
48
+ def list_peers(self):
49
+ """Request list of available peers from server"""
50
+ msg = {'cmd': 'list'}
51
+ self.sock.sendto(json.dumps(msg).encode(), self.server_addr)
52
+
53
+ def connect_to_peer(self, target_id):
54
+ """Initiate connection to another peer"""
55
+ msg = {
56
+ 'cmd': 'connect',
57
+ 'peer_id': self.peer_id,
58
+ 'target_id': target_id
59
+ }
60
+ self.sock.sendto(json.dumps(msg).encode(), self.server_addr)
61
+ print(f"Requesting connection to peer '{target_id}'...")
62
+
63
+ def punch_hole(self, peer_addr):
64
+ """Send initial packets to punch through NAT"""
65
+ punch_msg = json.dumps({
66
+ 'type': 'punch',
67
+ 'peer_id': self.peer_id
68
+ }).encode()
69
+
70
+ # Send multiple packets to ensure hole punching
71
+ for i in range(5):
72
+ self.sock.sendto(punch_msg, peer_addr)
73
+ time.sleep(0.1)
74
+
75
+ def send_message(self, peer_id, message):
76
+ """Send a message to a connected peer"""
77
+ if peer_id not in self.connected_peers:
78
+ print(f"Not connected to peer '{peer_id}'")
79
+ return
80
+
81
+ peer_addr = self.connected_peers[peer_id]
82
+ msg = {
83
+ 'type': 'message',
84
+ 'from': self.peer_id,
85
+ 'text': message
86
+ }
87
+ self.sock.sendto(json.dumps(msg).encode(), peer_addr)
88
+
89
+ def handle_incoming(self):
90
+ """Handle incoming messages"""
91
+ while self.running:
92
+ try:
93
+ data, addr = self.sock.recvfrom(4096)
94
+ msg = json.loads(data.decode())
95
+
96
+ # Response from server
97
+ if addr == self.server_addr:
98
+ if msg.get('status') == 'registered':
99
+ endpoint = msg.get('your_endpoint')
100
+ print(f"Server sees us at {endpoint['ip']}:{endpoint['port']}")
101
+
102
+ elif 'peers' in msg:
103
+ peers = msg['peers']
104
+ print("\nAvailable peers:")
105
+ for pid, info in peers.items():
106
+ if pid != self.peer_id:
107
+ print(f" - {pid} ({info['ip']}:{info['port']})")
108
+
109
+ elif msg.get('status') == 'found':
110
+ peer_endpoint = msg['peer_endpoint']
111
+ peer_addr = (peer_endpoint['ip'], peer_endpoint['port'])
112
+ print(f"Punching hole to {peer_addr}...")
113
+ self.punch_hole(peer_addr)
114
+
115
+ elif msg.get('cmd') == 'incoming_connection':
116
+ peer_id = msg['peer_id']
117
+ peer_endpoint = msg['peer_endpoint']
118
+ peer_addr = (peer_endpoint['ip'], peer_endpoint['port'])
119
+ print(f"\nIncoming connection from '{peer_id}' at {peer_addr}")
120
+ print("Punching hole back...")
121
+ self.punch_hole(peer_addr)
122
+
123
+ # Direct peer-to-peer messages
124
+ else:
125
+ msg_type = msg.get('type')
126
+
127
+ if msg_type == 'punch':
128
+ peer_id = msg.get('peer_id')
129
+ print(f"Received punch from '{peer_id}' at {addr}")
130
+ self.connected_peers[peer_id] = addr
131
+
132
+ # Send acknowledgment
133
+ ack = json.dumps({
134
+ 'type': 'ack',
135
+ 'peer_id': self.peer_id
136
+ }).encode()
137
+ self.sock.sendto(ack, addr)
138
+ print(f"✓ Connected to '{peer_id}'!")
139
+
140
+ elif msg_type == 'ack':
141
+ peer_id = msg.get('peer_id')
142
+ self.connected_peers[peer_id] = addr
143
+ print(f"✓ Connection established with '{peer_id}'!")
144
+
145
+ elif msg_type == 'message':
146
+ sender = msg.get('from')
147
+ text = msg.get('text')
148
+ print(f"\n[{sender}]: {text}")
149
+
150
+ except Exception as e:
151
+ if self.running:
152
+ print(f"Error: {e}")
153
+
154
+ def interactive_shell(self):
155
+ """Interactive command shell"""
156
+ print("\nCommands:")
157
+ print(" list - List available peers")
158
+ print(" connect <peer_id> - Connect to a peer")
159
+ print(" send <peer_id> <message> - Send message to peer")
160
+ print(" quit - Exit")
161
+ print()
162
+
163
+ while self.running:
164
+ try:
165
+ cmd = input("> ").strip()
166
+
167
+ if not cmd:
168
+ continue
169
+
170
+ parts = cmd.split(maxsplit=2)
171
+
172
+ if parts[0] == 'list':
173
+ self.list_peers()
174
+
175
+ elif parts[0] == 'connect' and len(parts) >= 2:
176
+ self.connect_to_peer(parts[1])
177
+
178
+ elif parts[0] == 'send' and len(parts) >= 3:
179
+ self.send_message(parts[1], parts[2])
180
+
181
+ elif parts[0] == 'quit':
182
+ self.running = False
183
+ break
184
+
185
+ else:
186
+ print("Unknown command")
187
+
188
+ except KeyboardInterrupt:
189
+ print("\nExiting...")
190
+ self.running = False
191
+ break
192
+
193
+ def run(self):
194
+ """Start the peer client"""
195
+ self.register()
196
+
197
+ # Start heartbeat thread
198
+ heartbeat_thread = threading.Thread(target=self.send_heartbeat, daemon=True)
199
+ heartbeat_thread.start()
200
+
201
+ # Start receiving thread
202
+ recv_thread = threading.Thread(target=self.handle_incoming, daemon=True)
203
+ recv_thread.start()
204
+
205
+ time.sleep(0.5) # Wait for registration
206
+
207
+ # Run interactive shell
208
+ self.interactive_shell()
209
+
210
+ self.sock.close()
211
+
212
+ if __name__ == '__main__':
213
+ if len(sys.argv) < 3:
214
+ print("Usage: python peer_client.py <peer_id> <server_host>")
215
+ print("Example: python peer_client.py Alice 192.168.1.100")
216
+ sys.exit(1)
217
+
218
+ peer_id = sys.argv[1]
219
+ server_host = sys.argv[2]
220
+
221
+ client = PeerClient(peer_id, server_host)
222
+ client.run()
223
+
224
+
225
+ 24.94.185.82
226
+
227
+ novus 73.217.240.123
ns2/lib/udp_server.py ADDED
@@ -0,0 +1,167 @@
1
+ import os
2
+ import socket
3
+ import time
4
+ from dataclasses import dataclass, asdict
5
+ import asyncio
6
+ from asyncio import StreamWriter, StreamReader
7
+ from nicegui import Event, app
8
+
9
+ from collections import deque
10
+ socket_received = Event()
11
+
12
+ socket_writer = None
13
+ socket_reader = None
14
+
15
+ async def socket_setup():
16
+ global socket_reader, socket_writer
17
+ try:
18
+ socket_reader, socket_writer = await asyncio.open_unix_connection("/tmp/serial.sock")
19
+ print("SOCKET OPENED")
20
+ await read_socket()
21
+
22
+ except FileNotFoundError:
23
+ print("SOCKET NOT AVAILABLE")
24
+ socket_received.emit("Socket Not Available")
25
+
26
+ #raise
27
+
28
+ except asyncio.CancelledError:
29
+ print("SOCKET LISTENER CANCELLED")
30
+ raise
31
+
32
+ finally:
33
+ await socket_cleanup()
34
+
35
+ async def socket_cleanup():
36
+ global socket_writer
37
+
38
+ print("SOCKET LISTENER CLOSED")
39
+ if socket_writer:
40
+ socket_writer.close()
41
+ await socket_writer.wait_closed()
42
+
43
+
44
+
45
+
46
+ async def read_socket():
47
+ global socket_reader
48
+ while True:
49
+ data = await socket_reader.read(128)
50
+ if data:
51
+ record_data(data)
52
+ # Emit event with the data - any subscribed UI can receive it
53
+ socket_received.emit(data.decode('utf-8', errors='ignore'))
54
+ else:
55
+ # Socket closed by remote end
56
+ break
57
+
58
+ #get_data()
59
+
60
+
61
+
62
+ def record_data(data):
63
+ latest = data.decode('utf-8', errors='ignore')
64
+ with open("data.txt", "a") as f:
65
+ f.writelines(latest)
66
+
67
+ with open("data.txt", "r+") as f:
68
+ lines = f.readlines()
69
+ n = len(lines)
70
+ if n >= 10000:
71
+ lines = lines[n-10000:]
72
+ f.seek(0) # go to start of file
73
+ f.truncate()
74
+ f.writelines(lines)
75
+
76
+
77
+
78
+
79
+ async def write_socket(command: str):
80
+ global socket_writer
81
+ command = command+"\r\n"
82
+ socket_writer.write(command.encode())
83
+ await socket_writer.drain()
84
+
85
+
86
+
87
+ def ReadWriteSocket(command: str) -> str:
88
+ command = command + "\r\n"
89
+
90
+ try:
91
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
92
+ sock.connect("/tmp/serial.sock")
93
+ sock.settimeout(4.0) # 4 second timeout
94
+
95
+ try:
96
+ sock.sendall(command.encode('utf-8'))
97
+ sock_file = sock.makefile('r')
98
+
99
+ while True:
100
+ line = sock_file.readline()
101
+
102
+ if any(marker in line for marker in ["$ER", "$RR", "$WR", "$GPNTL"]):
103
+ return line, None
104
+
105
+ finally:
106
+ sock.close()
107
+
108
+ except socket.timeout:
109
+ return "timeout"
110
+ except ConnectionRefusedError as e:
111
+ print("socket error?")
112
+ return "port open error"
113
+ except Exception as e:
114
+ print(e)
115
+ return "port write error"
116
+
117
+
118
+
119
+
120
+
121
+ def ReadNtlProperty(module: int, property :int) -> list[str]:
122
+ return ReadWriteSocket(f"$GPNTL,{module},{property},?")
123
+
124
+ def WriteNtlProperty(module: int, property :int, value :str):
125
+ return ReadWriteSocket(f"$GPNTL,{module},{property},{value}")
126
+
127
+ def ParseNtlResponse(response :str)->str:
128
+ fields = response.split(",")
129
+ if len(fields) == 4:
130
+ module = fields[1]
131
+ property = fields[2]
132
+ value = fields[3]
133
+ return value
134
+
135
+
136
+
137
+ def LoadConfig(file_name: str):
138
+
139
+ print("LOADING CONFIG...")
140
+
141
+ try:
142
+ with open(file_name, 'r') as f:
143
+ data = f.read()
144
+ except Exception as err:
145
+ print(f"file err: {err}")
146
+ return
147
+
148
+ for line in data.split('\n'):
149
+ # Skip comments
150
+ if "--" in line:
151
+ continue
152
+
153
+ # Process $WC commands
154
+ if "$WC" in line:
155
+ line = line.strip() # Remove whitespace and newlines
156
+
157
+ rsp, err = ReadWriteSocket(line)
158
+
159
+ if rsp.startswith("$ER"):
160
+ print("config load err")
161
+ return
162
+
163
+ if err is not None:
164
+ print("config error")
165
+ return
166
+
167
+ print(rsp)
ns2/snmp/__init__.py ADDED
File without changes
@@ -0,0 +1,38 @@
1
+ import asyncio
2
+
3
+ from dbus_next.aio import MessageBus
4
+ from dbus_next.constants import BusType
5
+
6
+ from snmp_interface import SnmpInterface
7
+ from pam_interface import PamInterface
8
+ from systemd_lib import *
9
+
10
+ from cockpit_dbus_superuser_service import Superuser
11
+ async def main():
12
+
13
+ bus = await MessageBus(bus_type=BusType.SYSTEM).connect()
14
+
15
+ snmpInterface = SnmpInterface('com.novus.ns.snmp')
16
+ bus.export('/com/novus/ns', snmpInterface)
17
+ snmpInterface.bus = bus
18
+
19
+ pamInterface = PamInterface('com.novus.ns.pam')
20
+ bus.export('/com/novus/ns', pamInterface)
21
+
22
+ userInterface = Superuser('com.novus.ns.super')
23
+ bus.export('/com/novus/ns', userInterface)
24
+
25
+ #firewallInterface = FirewalldInterface('com.novus.ns.firewall')
26
+ #bus.export('/com/novus/ns', firewallInterface)
27
+
28
+ #socketInterface = SocketInterface('com.novus.ns.socket')
29
+ #bus.export('/com/novus/ns', socketInterface)
30
+
31
+ print("Starting ns service... com.novus.ns")
32
+
33
+ await bus.request_name('com.novus.ns')
34
+ await asyncio.Event().wait()
35
+
36
+ bus.disconnect()
37
+
38
+ asyncio.run(main())
@@ -0,0 +1,19 @@
1
+ import pam
2
+ from dbus_next.service import ServiceInterface, method
3
+
4
+
5
+ class PamInterface(ServiceInterface):
6
+ def __init__(self, name):
7
+ super().__init__(name)
8
+
9
+ @method()
10
+ def Authenticate(self, username: 's', password: 's') -> 'b':
11
+ p = pam.pam()
12
+ if p.authenticate(username, password, print_failure_messages=True):
13
+ print("authentication successful")
14
+ return True
15
+ else:
16
+ print("authentication failed")
17
+
18
+ return False
19
+
@@ -0,0 +1,66 @@
1
+
2
+
3
+ from dataclasses import asdict
4
+ from dbus_next.service import ServiceInterface, method
5
+
6
+ from snmp_lib import *
7
+
8
+ class SnmpInterface(ServiceInterface):
9
+ def __init__(self, name):
10
+ super().__init__(name)
11
+ self.bus = None
12
+
13
+ @method()
14
+ async def Reset(self):
15
+ await ResetSnmpd(self.bus)
16
+
17
+ # ====================================================================
18
+ # V3 USERS
19
+ # ====================================================================
20
+ @method()
21
+ async def CreateV3User(self, v3User: 'a{ss}'):
22
+ await AddV3User(self.bus, V3User.from_dict(v3User))
23
+
24
+ @method()
25
+ async def GetV3UserByUsername(self, username :'s') -> 'a{ss}':
26
+ return asdict(await ReadV3UserByUsername(username))
27
+
28
+ @method()
29
+ async def GetV3Users(self) -> 'aa{ss}':
30
+ return [asdict(u) for u in (await ReadV3Users())]
31
+
32
+ @method()
33
+ async def ModifyV3User(self, initUser: 'a{ss}', finalUser: 'a{ss}'):
34
+ await EditV3User(self.bus, V3User.from_dict(initUser), V3User.from_dict(finalUser))
35
+
36
+ @method()
37
+ async def RemoveV3User(self, v3User: 'a{ss}'):
38
+ await DeleteV3User(self.bus, V3User.from_dict(v3User))
39
+
40
+ # ====================================================================
41
+ # V2 USERS
42
+ # ====================================================================
43
+
44
+ @method()
45
+ async def CreateV2User(self, v2User: 'a{ss}'):
46
+ await AddV2User(self.bus, V2User.from_dict(v2User))
47
+
48
+ @method()
49
+ async def GetV2UserByCommunity(self, community :'s') -> 'a{ss}':
50
+ return asdict(await ReadV2UserByCommunity(community))
51
+
52
+ @method()
53
+ async def GetV2Users(self) -> 'aa{ss}':
54
+ return [asdict(u) for u in await ReadV2Users()]
55
+
56
+ @method()
57
+ async def ModifyV2User(self, editUser: 'a{ss}'):
58
+ await EditV2User(self.bus, V2User.from_dict(editUser))
59
+
60
+ @method()
61
+ async def RemoveV2User(self, v2User: 'a{ss}'):
62
+ await DeleteV2User(self.bus, V2User.from_dict(v2User))
63
+
64
+ # ====================================================================
65
+ #
66
+ # ====================================================================
ns2/ui/__init__.py ADDED
File without changes
@@ -0,0 +1,105 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+ <svg
5
+ version="1.1"
6
+ id="svg1"
7
+ width="496"
8
+ height="59.648041"
9
+ viewBox="0 0 496 59.648041"
10
+ sodipodi:docname="NOVUS_TEMP.svg"
11
+ inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
12
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
14
+ xmlns:xlink="http://www.w3.org/1999/xlink"
15
+ xmlns="http://www.w3.org/2000/svg"
16
+ xmlns:svg="http://www.w3.org/2000/svg">
17
+ <defs
18
+ id="defs1">
19
+ <mask
20
+ maskUnits="userSpaceOnUse"
21
+ x="0"
22
+ y="0"
23
+ width="1"
24
+ height="1"
25
+ id="mask1">
26
+ <image
27
+ width="1"
28
+ height="1"
29
+ style="image-rendering:optimizeSpeed"
30
+ preserveAspectRatio="none"
31
+ xlink:href="data:image/png;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDlmt+AAABOklEQVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN8P8Bz4xOOtDMgmgAAAAASUVORK5CYII="
32
+ id="image1" />
33
+ </mask>
34
+ </defs>
35
+ <sodipodi:namedview
36
+ id="namedview1"
37
+ pagecolor="#ffffff"
38
+ bordercolor="#000000"
39
+ borderopacity="0.25"
40
+ inkscape:showpageshadow="2"
41
+ inkscape:pageopacity="0.0"
42
+ inkscape:pagecheckerboard="0"
43
+ inkscape:deskcolor="#d1d1d1"
44
+ inkscape:zoom="2.6587786"
45
+ inkscape:cx="227.73615"
46
+ inkscape:cy="30.277061"
47
+ inkscape:window-width="2560"
48
+ inkscape:window-height="1369"
49
+ inkscape:window-x="1912"
50
+ inkscape:window-y="-8"
51
+ inkscape:window-maximized="1"
52
+ inkscape:current-layer="g9">
53
+ <inkscape:page
54
+ x="0"
55
+ y="0"
56
+ inkscape:label="1"
57
+ id="page1"
58
+ width="496"
59
+ height="59.648041"
60
+ margin="0"
61
+ bleed="0" />
62
+ </sodipodi:namedview>
63
+ <g
64
+ id="g1"
65
+ inkscape:groupmode="layer"
66
+ inkscape:label="1"
67
+ transform="translate(-39.071831,-9.3639688)">
68
+ <g
69
+ id="g9">
70
+ <g
71
+ id="g10"
72
+ transform="translate(0.192,-287.808)">
73
+ <path
74
+ id="path8"
75
+ style="fill:#d40000;fill-opacity:1"
76
+ d="m 160.81055,309.21094 c -12.84512,-0.0652 -20.43225,0.0192 -21.86914,0.24218 -4.46679,0.69304 -7.73704,2.34066 -8.70703,4.38477 -0.43855,0.92419 -0.51383,1.92895 -0.42383,5.67773 0.10591,4.41164 0.13727,4.59226 1,5.72266 1.09141,1.43003 3.03378,2.60276 5.35742,3.23438 1.48222,0.40293 5.08007,0.46661 23.35156,0.41211 21.45449,-0.0639 21.61108,-0.0695 23.32031,-0.76954 2.28736,-0.93679 4.14144,-2.2517 4.70313,-3.33789 0.336,-0.64975 0.45703,-2.13532 0.45703,-5.58398 0,-4.13885 -0.0771,-4.82059 -0.64062,-5.73242 -0.7787,-1.25995 -2.67209,-2.55285 -5.08008,-3.4668 -1.75555,-0.66631 -2.28598,-0.6859 -21.46875,-0.7832 z m -22.41016,4.72851 h 20.47852 20.48047 v 5.28125 5.2793 h -20.48047 -20.47852 v -5.2793 z" />
77
+ <path
78
+ style="fill:#d40000;fill-opacity:1"
79
+ d="m 346.39982,325.83142 v -3.56843 l 33.2,-0.0815 33.2,-0.0815 0.0929,-2.64 0.0929,-2.64 H 385.3346 c -30.75812,0 -31.23633,-0.0276 -35.53424,-2.05036 -2.85159,-1.34207 -4.26887,-2.41053 -5.36764,-4.04655 -1.72803,-2.57299 -1.46458,-5.45181 0.71534,-7.81675 2.39163,-2.59461 7.60208,-4.69286 12.6517,-5.09484 1.20999,-0.0963 15.84398,-0.26177 32.51998,-0.36765 l 30.32,-0.19252 v 3.54433 3.54434 h -32.63992 -32.64 v 2.70866 2.70866 l 28.72,0.0913 28.72,0.0913 2.56,0.90168 c 10.42683,3.67251 11.86109,11.61536 2.89606,16.03829 -4.43255,2.1868 -2.95533,2.09923 -39.13606,2.32012 l -32.72,0.19976 z"
80
+ id="path7" />
81
+ <path
82
+ style="fill:#d40000;fill-opacity:1"
83
+ d="m 284.05624,328.96501 c -3.08618,-0.62385 -6.5662,-2.83146 -7.59276,-4.81661 -0.36374,-0.7034 -0.46365,-2.41703 -0.46365,-7.9525 v -7.05589 h 4.48 4.48 v 7.68 7.68 h 20.8 20.8 v -7.68 -7.68 h 4.48 4.48 v 7.63685 c 0,7.30155 -0.0299,7.67479 -0.67986,8.50114 -0.87514,1.11257 -2.78266,2.31017 -5.04617,3.16817 -1.7575,0.66619 -2.22659,0.68122 -23.07397,0.73927 -11.704,0.0326 -21.90261,-0.0666 -22.66359,-0.22043 z"
84
+ id="path6" />
85
+ <path
86
+ style="fill:#d40000;fill-opacity:1"
87
+ d="m 215.44365,328.67861 c -2.47395,-0.79086 -4.67747,-2.25736 -6.74123,-4.48646 -1.86158,-2.01073 -3.00952,-3.86657 -8.41753,-13.60839 l -3.55495,-6.40375 -33.64505,-0.0815 -33.64506,-0.0815 v -3.35853 -3.35847 l 37.6,-0.048 c 20.68,-0.0264 37.74614,-0.0624 37.92476,-0.08 0.17862,-0.0176 3.60419,5.584 7.61238,12.448 l 7.28762,12.48 2.70762,0.21294 c 3.65736,0.28763 18.403,0.33585 21.33917,0.0698 l 2.36196,-0.21403 7.42324,-12.43291 7.42325,-12.4329 37.2,-10e-4 37.2,-0.001 v 3.30763 3.30763 l -17.52,0.21205 c -9.636,0.11663 -24.5079,0.21219 -33.04866,0.21237 l -15.52865,3.2e-4 -5.42488,9.36 c -5.74382,9.91031 -7.14759,11.78822 -10.18204,13.62118 -3.21068,1.93942 -3.56417,1.9726 -20.85577,1.95781 -14.30467,-0.0122 -15.84106,-0.0649 -17.51618,-0.60039 z"
88
+ id="path5" />
89
+ <path
90
+ style="fill:#d40000;fill-opacity:1"
91
+ d="m 38.881629,317.70001 c 0.0011,-7.3024 0.129529,-12.06008 0.34659,-12.84183 0.852584,-3.0706 6.356793,-6.59257 11.344636,-7.25906 1.586502,-0.212 6.923524,-0.29784 13.92,-0.2239 10.884252,0.11504 11.429002,0.14992 13.358059,0.85547 2.82221,1.03223 6.377,3.66107 7.57671,5.60313 l 0.97221,1.57381 0.16,8.34619 0.16,8.34619 h 12.160001 12.159995 l 0.0838,-12.4 0.0838,-12.4 h 5.75624 5.75624 v 12.03164 c 0,10.43419 -0.0689,12.17686 -0.51905,13.12545 -1.14246,2.40757 -5.59618,5.3733 -9.42094,6.27342 -1.25536,0.29543 -5.17152,0.40949 -14.060005,0.40949 -12.000891,0 -12.374771,-0.0189 -14.434741,-0.73103 -3.96451,-1.37046 -7.17819,-3.88253 -8.480377,-6.62897 -0.734317,-1.54874 -0.758717,-1.85375 -0.761747,-9.52 l -0.003,-7.92 h -12.160001 -12.16 v 12.48 12.48 h -5.92 -5.92 z"
92
+ id="path4" />
93
+ <path
94
+ style="fill:#000000;fill-opacity:1"
95
+ d="m 38.879829,340.82001 v -3.2 h 247.999991 248 v 3.2 3.2 h -248 -247.999991 z"
96
+ id="path3"
97
+ sodipodi:nodetypes="ccccccccc" />
98
+ <path
99
+ style="fill:#d40000;fill-opacity:1"
100
+ d="m 39.005593,356.31384 c 0.10683,-0.2784 0.194236,-1.1424 0.194236,-1.92 v -1.41383 h 247.679991 247.68 v 1.92 1.92 H 286.68558 c -225.897402,0 -247.857003,-0.0449 -247.679987,-0.50617 z"
101
+ id="path2" />
102
+ </g>
103
+ </g>
104
+ </g>
105
+ </svg>
Binary file