neuronum 5.9.0__py3-none-any.whl → 6.0.1__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 +1137 -1143
- neuronum/__init__.py +1 -1
- neuronum/neuronum.py +519 -519
- {neuronum-5.9.0.dist-info → neuronum-6.0.1.dist-info}/METADATA +252 -248
- neuronum-6.0.1.dist-info/RECORD +10 -0
- {neuronum-5.9.0.dist-info → neuronum-6.0.1.dist-info}/licenses/LICENSE.md +47 -47
- neuronum-5.9.0.dist-info/RECORD +0 -10
- {neuronum-5.9.0.dist-info → neuronum-6.0.1.dist-info}/WHEEL +0 -0
- {neuronum-5.9.0.dist-info → neuronum-6.0.1.dist-info}/entry_points.txt +0 -0
- {neuronum-5.9.0.dist-info → neuronum-6.0.1.dist-info}/top_level.txt +0 -0
neuronum/neuronum.py
CHANGED
|
@@ -1,519 +1,519 @@
|
|
|
1
|
-
import aiohttp
|
|
2
|
-
from typing import Optional, AsyncGenerator
|
|
3
|
-
import ssl
|
|
4
|
-
import websockets
|
|
5
|
-
import json
|
|
6
|
-
import asyncio
|
|
7
|
-
|
|
8
|
-
class Cell:
|
|
9
|
-
def __init__(self, host: str, password: str, network: str, synapse: str):
|
|
10
|
-
self.host = host
|
|
11
|
-
self.password = password
|
|
12
|
-
self.network = network
|
|
13
|
-
self.synapse = synapse
|
|
14
|
-
self.queue = asyncio.Queue()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def to_dict(self) -> dict:
|
|
18
|
-
return {
|
|
19
|
-
"host": self.host,
|
|
20
|
-
"password": self.password,
|
|
21
|
-
"synapse": self.synapse
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def __repr__(self) -> str:
|
|
26
|
-
return f"Cell(host={self.host}, password={self.password}, network={self.network}, synapse={self.synapse})"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
async def stream(self, label: str, data: dict, stx: Optional[str] = None, retry_delay: int = 3):
|
|
30
|
-
context = ssl.create_default_context()
|
|
31
|
-
context.check_hostname = True
|
|
32
|
-
context.verify_mode = ssl.CERT_REQUIRED
|
|
33
|
-
|
|
34
|
-
while True:
|
|
35
|
-
try:
|
|
36
|
-
reader, writer = await asyncio.open_connection(self.network, 55555, ssl=context, server_hostname=self.network)
|
|
37
|
-
|
|
38
|
-
credentials = f"{self.host}\n{self.password}\n{self.synapse}\n{stx}\n"
|
|
39
|
-
writer.write(credentials.encode("utf-8"))
|
|
40
|
-
await writer.drain()
|
|
41
|
-
|
|
42
|
-
response = await reader.read(1024)
|
|
43
|
-
response_text = response.decode("utf-8").strip()
|
|
44
|
-
|
|
45
|
-
if "Authentication successful" not in response_text:
|
|
46
|
-
print("Authentication failed, retrying...")
|
|
47
|
-
writer.close()
|
|
48
|
-
await writer.wait_closed()
|
|
49
|
-
await asyncio.sleep(retry_delay)
|
|
50
|
-
continue
|
|
51
|
-
|
|
52
|
-
stream_payload = {
|
|
53
|
-
"label": label,
|
|
54
|
-
"data": data,
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
writer.write(json.dumps(stream_payload).encode("utf-8"))
|
|
58
|
-
await writer.drain()
|
|
59
|
-
|
|
60
|
-
response = await reader.read(1024)
|
|
61
|
-
response_text = response.decode("utf-8").strip()
|
|
62
|
-
|
|
63
|
-
if response_text == "Sent":
|
|
64
|
-
print(f"Success: {response_text} - {stream_payload}")
|
|
65
|
-
break
|
|
66
|
-
else:
|
|
67
|
-
print(f"Error sending: {stream_payload}")
|
|
68
|
-
|
|
69
|
-
except (ssl.SSLError, ConnectionError) as e:
|
|
70
|
-
print(f"Connection error: {e}, retrying...")
|
|
71
|
-
await asyncio.sleep(retry_delay)
|
|
72
|
-
|
|
73
|
-
except Exception as e:
|
|
74
|
-
print(f"Unexpected error: {e}, retrying...")
|
|
75
|
-
await asyncio.sleep(retry_delay)
|
|
76
|
-
|
|
77
|
-
finally:
|
|
78
|
-
if 'writer' in locals():
|
|
79
|
-
writer.close()
|
|
80
|
-
await writer.wait_closed()
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
async def sync(self, stx: Optional[str] = None) -> AsyncGenerator[str, None]:
|
|
84
|
-
full_url = f"wss://{self.network}/sync/{stx}"
|
|
85
|
-
auth_payload = {
|
|
86
|
-
"host": self.host,
|
|
87
|
-
"password": self.password,
|
|
88
|
-
"synapse": self.synapse,
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
while True:
|
|
92
|
-
try:
|
|
93
|
-
async with websockets.connect(full_url) as ws:
|
|
94
|
-
await ws.send(json.dumps(auth_payload))
|
|
95
|
-
print("Connected to WebSocket.")
|
|
96
|
-
|
|
97
|
-
while True:
|
|
98
|
-
try:
|
|
99
|
-
raw_operation = await ws.recv()
|
|
100
|
-
operation = json.loads(raw_operation)
|
|
101
|
-
yield operation
|
|
102
|
-
|
|
103
|
-
except asyncio.TimeoutError:
|
|
104
|
-
print("No data received. Continuing...")
|
|
105
|
-
except websockets.exceptions.ConnectionClosedError as e:
|
|
106
|
-
print(f"Connection closed with error: {e}. Reconnecting...")
|
|
107
|
-
break
|
|
108
|
-
except Exception as e:
|
|
109
|
-
print(f"Unexpected error in recv loop: {e}")
|
|
110
|
-
break
|
|
111
|
-
|
|
112
|
-
except websockets.exceptions.WebSocketException as e:
|
|
113
|
-
print(f"WebSocket error occurred: {e}. Retrying in 5 seconds...")
|
|
114
|
-
except Exception as e:
|
|
115
|
-
print(f"General error occurred: {e}. Retrying in 5 seconds...")
|
|
116
|
-
|
|
117
|
-
await asyncio.sleep(3)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
async def create_tx(self, descr: str, key_values: dict, stx: str, label: str, partners: list):
|
|
121
|
-
url = f"https://{self.network}/api/create_tx"
|
|
122
|
-
|
|
123
|
-
TX = {
|
|
124
|
-
"descr": descr,
|
|
125
|
-
"key_values": key_values,
|
|
126
|
-
"stx": stx,
|
|
127
|
-
"label": label,
|
|
128
|
-
"partners": partners,
|
|
129
|
-
"cell": self.to_dict()
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async with aiohttp.ClientSession() as session:
|
|
133
|
-
try:
|
|
134
|
-
async with session.post(url, json=TX) as response:
|
|
135
|
-
response.raise_for_status()
|
|
136
|
-
data = await response.json()
|
|
137
|
-
return data["txID"]
|
|
138
|
-
|
|
139
|
-
except aiohttp.ClientError as e:
|
|
140
|
-
print(f"Error sending request: {e}")
|
|
141
|
-
except Exception as e:
|
|
142
|
-
print(f"Unexpected error: {e}")
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
async def delete_tx(self, txID: str):
|
|
146
|
-
url = f"https://{self.network}/api/delete_tx"
|
|
147
|
-
|
|
148
|
-
TX = {
|
|
149
|
-
"txID": txID,
|
|
150
|
-
"cell": self.to_dict()
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
async with aiohttp.ClientSession() as session:
|
|
154
|
-
try:
|
|
155
|
-
async with session.post(url, json=TX) as response:
|
|
156
|
-
response.raise_for_status()
|
|
157
|
-
data = await response.json()
|
|
158
|
-
print(f"Response from Neuronum: {data}")
|
|
159
|
-
return data
|
|
160
|
-
|
|
161
|
-
except aiohttp.ClientError as e:
|
|
162
|
-
print(f"Error sending request: {e}")
|
|
163
|
-
except Exception as e:
|
|
164
|
-
print(f"Unexpected error: {e}")
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
async def activate_tx(self, txID: str, data: dict):
|
|
168
|
-
url = f"https://{self.network}/api/activate_tx/{txID}"
|
|
169
|
-
TX = {
|
|
170
|
-
"data": data,
|
|
171
|
-
"cell": self.to_dict()
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async with aiohttp.ClientSession() as session:
|
|
175
|
-
try:
|
|
176
|
-
async with session.post(url, json=TX) as response:
|
|
177
|
-
response.raise_for_status()
|
|
178
|
-
data = await response.json()
|
|
179
|
-
if data.get("success") == True:
|
|
180
|
-
if "json" in data.get("response"):
|
|
181
|
-
return data.get("response").get("json")
|
|
182
|
-
elif "html" in data.get("response"):
|
|
183
|
-
return "Info: HTML response available. Please activate TX in browser."
|
|
184
|
-
else:
|
|
185
|
-
return "Info: Response received but contains no usable content."
|
|
186
|
-
else:
|
|
187
|
-
print(data["success"], data["message"])
|
|
188
|
-
|
|
189
|
-
except aiohttp.ClientError as e:
|
|
190
|
-
print(f"Error sending request: {e}")
|
|
191
|
-
except Exception as e:
|
|
192
|
-
print(f"Unexpected error: {e}")
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
async def tx_response(self, txID: str, client: str, data: dict):
|
|
196
|
-
url = f"https://{self.network}/api/tx_response/{txID}"
|
|
197
|
-
|
|
198
|
-
tx_response = {
|
|
199
|
-
"client": client,
|
|
200
|
-
"data": data,
|
|
201
|
-
"cell": self.to_dict()
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
async with aiohttp.ClientSession() as session:
|
|
205
|
-
try:
|
|
206
|
-
for _ in range(2):
|
|
207
|
-
async with session.post(url, json=tx_response) as response:
|
|
208
|
-
response.raise_for_status()
|
|
209
|
-
data = await response.json()
|
|
210
|
-
print(data["message"])
|
|
211
|
-
|
|
212
|
-
except aiohttp.ClientError as e:
|
|
213
|
-
print(f"Error sending request: {e}")
|
|
214
|
-
except Exception as e:
|
|
215
|
-
print(f"Unexpected error: {e}")
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
async def create_ctx(self, descr: str, partners: list):
|
|
219
|
-
url = f"https://{self.network}/api/create_ctx"
|
|
220
|
-
|
|
221
|
-
CTX = {
|
|
222
|
-
"descr": descr,
|
|
223
|
-
"partners": partners,
|
|
224
|
-
"cell": self.to_dict()
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
async with aiohttp.ClientSession() as session:
|
|
228
|
-
try:
|
|
229
|
-
async with session.post(url, json=CTX) as response:
|
|
230
|
-
response.raise_for_status()
|
|
231
|
-
data = await response.json()
|
|
232
|
-
return data["ctxID"]
|
|
233
|
-
|
|
234
|
-
except aiohttp.ClientError as e:
|
|
235
|
-
print(f"Error sending request: {e}")
|
|
236
|
-
except Exception as e:
|
|
237
|
-
print(f"Unexpected error: {e}")
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
async def delete_ctx(self, ctxID: str):
|
|
241
|
-
url = f"https://{self.network}/api/delete_ctx"
|
|
242
|
-
|
|
243
|
-
CTX = {
|
|
244
|
-
"ctxID": ctxID,
|
|
245
|
-
"cell": self.to_dict()
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
async with aiohttp.ClientSession() as session:
|
|
249
|
-
try:
|
|
250
|
-
async with session.post(url, json=CTX) as response:
|
|
251
|
-
response.raise_for_status()
|
|
252
|
-
data = await response.json()
|
|
253
|
-
print(f"Response from Neuronum: {data}")
|
|
254
|
-
return data
|
|
255
|
-
|
|
256
|
-
except aiohttp.ClientError as e:
|
|
257
|
-
print(f"Error sending request: {e}")
|
|
258
|
-
except Exception as e:
|
|
259
|
-
print(f"Unexpected error: {e}")
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
async def create_stx(self, descr: str, partners: list):
|
|
263
|
-
url = f"https://{self.network}/api/create_stx"
|
|
264
|
-
|
|
265
|
-
STX = {
|
|
266
|
-
"descr": descr,
|
|
267
|
-
"partners": partners,
|
|
268
|
-
"cell": self.to_dict()
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
async with aiohttp.ClientSession() as session:
|
|
272
|
-
try:
|
|
273
|
-
async with session.post(url, json=STX) as response:
|
|
274
|
-
response.raise_for_status()
|
|
275
|
-
data = await response.json()
|
|
276
|
-
return data["stxID"]
|
|
277
|
-
|
|
278
|
-
except aiohttp.ClientError as e:
|
|
279
|
-
print(f"Error sending request: {e}")
|
|
280
|
-
except Exception as e:
|
|
281
|
-
print(f"Unexpected error: {e}")
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
async def delete_stx(self, stxID: str):
|
|
285
|
-
url = f"https://{self.network}/api/delete_stx"
|
|
286
|
-
|
|
287
|
-
STX = {
|
|
288
|
-
"stxID": stxID,
|
|
289
|
-
"cell": self.to_dict()
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
async with aiohttp.ClientSession() as session:
|
|
293
|
-
try:
|
|
294
|
-
async with session.post(url, json=STX) as response:
|
|
295
|
-
response.raise_for_status()
|
|
296
|
-
data = await response.json()
|
|
297
|
-
print(f"Response from Neuronum: {data}")
|
|
298
|
-
return data
|
|
299
|
-
|
|
300
|
-
except aiohttp.ClientError as e:
|
|
301
|
-
print(f"Error sending request: {e}")
|
|
302
|
-
except Exception as e:
|
|
303
|
-
print(f"Unexpected error: {e}")
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
async def list_cells(self):
|
|
307
|
-
full_url = f"https://{self.network}/api/list_cells"
|
|
308
|
-
|
|
309
|
-
list_cells_payload = {
|
|
310
|
-
"cell": self.to_dict()
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
async with aiohttp.ClientSession() as session:
|
|
314
|
-
try:
|
|
315
|
-
async with session.get(full_url, json=list_cells_payload) as response:
|
|
316
|
-
response.raise_for_status()
|
|
317
|
-
data = await response.json()
|
|
318
|
-
return data.get("Cells", [])
|
|
319
|
-
|
|
320
|
-
except aiohttp.ClientError as e:
|
|
321
|
-
print(f"Error sending request: {e}")
|
|
322
|
-
except Exception as e:
|
|
323
|
-
print(f"Unexpected error: {e}")
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
async def list_tx(self):
|
|
327
|
-
full_url = f"https://{self.network}/api/list_tx"
|
|
328
|
-
|
|
329
|
-
list_tx_payload = {
|
|
330
|
-
"cell": self.to_dict()
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
async with aiohttp.ClientSession() as session:
|
|
334
|
-
try:
|
|
335
|
-
async with session.get(full_url, json=list_tx_payload) as response:
|
|
336
|
-
response.raise_for_status()
|
|
337
|
-
data = await response.json()
|
|
338
|
-
return data.get("Transmitters", [])
|
|
339
|
-
|
|
340
|
-
except aiohttp.ClientError as e:
|
|
341
|
-
print(f"Error sending request: {e}")
|
|
342
|
-
except Exception as e:
|
|
343
|
-
print(f"Unexpected error: {e}")
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
async def list_ctx(self):
|
|
347
|
-
full_url = f"https://{self.network}/api/list_ctx"
|
|
348
|
-
|
|
349
|
-
list_ctx_payload = {
|
|
350
|
-
"cell": self.to_dict()
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
async with aiohttp.ClientSession() as session:
|
|
354
|
-
try:
|
|
355
|
-
async with session.get(full_url, json=list_ctx_payload) as response:
|
|
356
|
-
response.raise_for_status()
|
|
357
|
-
data = await response.json()
|
|
358
|
-
return data.get("Circuits", [])
|
|
359
|
-
|
|
360
|
-
except aiohttp.ClientError as e:
|
|
361
|
-
print(f"Error sending request: {e}")
|
|
362
|
-
except Exception as e:
|
|
363
|
-
print(f"Unexpected error: {e}")
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
async def list_stx(self):
|
|
367
|
-
full_url = f"https://{self.network}/api/list_stx"
|
|
368
|
-
|
|
369
|
-
list_stx_payload = {
|
|
370
|
-
"cell": self.to_dict()
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
async with aiohttp.ClientSession() as session:
|
|
374
|
-
try:
|
|
375
|
-
async with session.get(full_url, json=list_stx_payload) as response:
|
|
376
|
-
response.raise_for_status()
|
|
377
|
-
data = await response.json()
|
|
378
|
-
return data.get("Streams", [])
|
|
379
|
-
|
|
380
|
-
except aiohttp.ClientError as e:
|
|
381
|
-
print(f"Error sending request: {e}")
|
|
382
|
-
except Exception as e:
|
|
383
|
-
print(f"Unexpected error: {e}")
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
async def list_nodes(self):
|
|
387
|
-
full_url = f"https://{self.network}/api/list_nodes"
|
|
388
|
-
|
|
389
|
-
list_nodes_payload = {
|
|
390
|
-
"cell": self.to_dict()
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
async with aiohttp.ClientSession() as session:
|
|
394
|
-
try:
|
|
395
|
-
async with session.get(full_url, json=list_nodes_payload) as response:
|
|
396
|
-
response.raise_for_status()
|
|
397
|
-
data = await response.json()
|
|
398
|
-
return data.get("Nodes", [])
|
|
399
|
-
|
|
400
|
-
except aiohttp.ClientError as e:
|
|
401
|
-
print(f"Error sending request: {e}")
|
|
402
|
-
except Exception as e:
|
|
403
|
-
print(f"Unexpected error: {e}")
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
async def store(self, label: str, data: dict, ctx: Optional[str] = None):
|
|
407
|
-
full_url = f"https://{self.network}/api/store_in_ctx/{ctx}" if ctx else f"https://{self.network}/api/store"
|
|
408
|
-
|
|
409
|
-
store_payload = {
|
|
410
|
-
"label": label,
|
|
411
|
-
"data": data,
|
|
412
|
-
"cell": self.to_dict()
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
async with aiohttp.ClientSession() as session:
|
|
416
|
-
try:
|
|
417
|
-
async with session.post(full_url, json=store_payload) as response:
|
|
418
|
-
response.raise_for_status()
|
|
419
|
-
data = await response.json()
|
|
420
|
-
print(f"Response from Neuronum: {data}")
|
|
421
|
-
return data
|
|
422
|
-
|
|
423
|
-
except aiohttp.ClientError as e:
|
|
424
|
-
print(f"Error sending request: {e}")
|
|
425
|
-
except Exception as e:
|
|
426
|
-
print(f"Unexpected error: {e}")
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
async def load(self, label: str, ctx: Optional[str] = None):
|
|
430
|
-
full_url = f"https://{self.network}/api/load_from_ctx/{ctx}" if ctx else f"https://{self.network}/api/load"
|
|
431
|
-
|
|
432
|
-
load_payload = {
|
|
433
|
-
"label": label,
|
|
434
|
-
"cell": self.to_dict()
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
async with aiohttp.ClientSession() as session:
|
|
438
|
-
try:
|
|
439
|
-
async with session.post(full_url, json=load_payload) as response:
|
|
440
|
-
response.raise_for_status()
|
|
441
|
-
data = await response.json()
|
|
442
|
-
return data
|
|
443
|
-
|
|
444
|
-
except aiohttp.ClientError as e:
|
|
445
|
-
print(f"Error sending request: {e}")
|
|
446
|
-
except Exception as e:
|
|
447
|
-
print(f"Unexpected error: {e}")
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
async def delete(self, label: str, ctx: Optional[str] = None):
|
|
451
|
-
full_url = f"https://{self.network}/api/delete_from_ctx/{ctx}" if ctx else f"https://{self.network}/api/delete"
|
|
452
|
-
|
|
453
|
-
delete_payload = {
|
|
454
|
-
"label": label,
|
|
455
|
-
"cell": self.to_dict()
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
async with aiohttp.ClientSession() as session:
|
|
459
|
-
try:
|
|
460
|
-
async with session.post(full_url, json=delete_payload) as response:
|
|
461
|
-
response.raise_for_status()
|
|
462
|
-
data = await response.json()
|
|
463
|
-
print(f"Response from Neuronum: {data}")
|
|
464
|
-
return data
|
|
465
|
-
|
|
466
|
-
except aiohttp.ClientError as e:
|
|
467
|
-
print(f"Error sending request: {e}")
|
|
468
|
-
except Exception as e:
|
|
469
|
-
print(f"Unexpected error: {e}")
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
async def clear(self, ctx: Optional[str] = None):
|
|
473
|
-
full_url = f"https://{self.network}/api/clear_ctx/{ctx}" if ctx else f"https://{self.network}/api/clear"
|
|
474
|
-
|
|
475
|
-
clear_payload = {
|
|
476
|
-
"cell": self.to_dict()
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
async with aiohttp.ClientSession() as session:
|
|
480
|
-
try:
|
|
481
|
-
async with session.post(full_url, json=clear_payload) as response:
|
|
482
|
-
response.raise_for_status()
|
|
483
|
-
data = await response.json()
|
|
484
|
-
print(f"Response from Neuronum: {data}")
|
|
485
|
-
return data
|
|
486
|
-
|
|
487
|
-
except aiohttp.ClientError as e:
|
|
488
|
-
print(f"Error sending request: {e}")
|
|
489
|
-
except Exception as e:
|
|
490
|
-
print(f"Unexpected error: {e}")
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
async def notify(self, receiver: str, title: str, message: str):
|
|
494
|
-
full_url = f"https://{self.network}/api/notify"
|
|
495
|
-
|
|
496
|
-
notify_payload = {
|
|
497
|
-
"receiver": receiver,
|
|
498
|
-
"notification": {
|
|
499
|
-
"title": title,
|
|
500
|
-
"message": message
|
|
501
|
-
},
|
|
502
|
-
"cell": self.to_dict()
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
async with aiohttp.ClientSession() as session:
|
|
506
|
-
try:
|
|
507
|
-
async with session.post(full_url, json=notify_payload) as response:
|
|
508
|
-
response.raise_for_status()
|
|
509
|
-
data = await response.json()
|
|
510
|
-
print(f"Notification sent successfully: {data}")
|
|
511
|
-
return data
|
|
512
|
-
|
|
513
|
-
except aiohttp.ClientError as e:
|
|
514
|
-
print(f"HTTP error while sending notification: {e}")
|
|
515
|
-
except Exception as e:
|
|
516
|
-
print(f"Unexpected error: {e}")
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
__all__ = ['Cell']
|
|
1
|
+
import aiohttp
|
|
2
|
+
from typing import Optional, AsyncGenerator
|
|
3
|
+
import ssl
|
|
4
|
+
import websockets
|
|
5
|
+
import json
|
|
6
|
+
import asyncio
|
|
7
|
+
|
|
8
|
+
class Cell:
|
|
9
|
+
def __init__(self, host: str, password: str, network: str, synapse: str):
|
|
10
|
+
self.host = host
|
|
11
|
+
self.password = password
|
|
12
|
+
self.network = network
|
|
13
|
+
self.synapse = synapse
|
|
14
|
+
self.queue = asyncio.Queue()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def to_dict(self) -> dict:
|
|
18
|
+
return {
|
|
19
|
+
"host": self.host,
|
|
20
|
+
"password": self.password,
|
|
21
|
+
"synapse": self.synapse
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def __repr__(self) -> str:
|
|
26
|
+
return f"Cell(host={self.host}, password={self.password}, network={self.network}, synapse={self.synapse})"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def stream(self, label: str, data: dict, stx: Optional[str] = None, retry_delay: int = 3):
|
|
30
|
+
context = ssl.create_default_context()
|
|
31
|
+
context.check_hostname = True
|
|
32
|
+
context.verify_mode = ssl.CERT_REQUIRED
|
|
33
|
+
|
|
34
|
+
while True:
|
|
35
|
+
try:
|
|
36
|
+
reader, writer = await asyncio.open_connection(self.network, 55555, ssl=context, server_hostname=self.network)
|
|
37
|
+
|
|
38
|
+
credentials = f"{self.host}\n{self.password}\n{self.synapse}\n{stx}\n"
|
|
39
|
+
writer.write(credentials.encode("utf-8"))
|
|
40
|
+
await writer.drain()
|
|
41
|
+
|
|
42
|
+
response = await reader.read(1024)
|
|
43
|
+
response_text = response.decode("utf-8").strip()
|
|
44
|
+
|
|
45
|
+
if "Authentication successful" not in response_text:
|
|
46
|
+
print("Authentication failed, retrying...")
|
|
47
|
+
writer.close()
|
|
48
|
+
await writer.wait_closed()
|
|
49
|
+
await asyncio.sleep(retry_delay)
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
stream_payload = {
|
|
53
|
+
"label": label,
|
|
54
|
+
"data": data,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
writer.write(json.dumps(stream_payload).encode("utf-8"))
|
|
58
|
+
await writer.drain()
|
|
59
|
+
|
|
60
|
+
response = await reader.read(1024)
|
|
61
|
+
response_text = response.decode("utf-8").strip()
|
|
62
|
+
|
|
63
|
+
if response_text == "Sent":
|
|
64
|
+
print(f"Success: {response_text} - {stream_payload}")
|
|
65
|
+
break
|
|
66
|
+
else:
|
|
67
|
+
print(f"Error sending: {stream_payload}")
|
|
68
|
+
|
|
69
|
+
except (ssl.SSLError, ConnectionError) as e:
|
|
70
|
+
print(f"Connection error: {e}, retrying...")
|
|
71
|
+
await asyncio.sleep(retry_delay)
|
|
72
|
+
|
|
73
|
+
except Exception as e:
|
|
74
|
+
print(f"Unexpected error: {e}, retrying...")
|
|
75
|
+
await asyncio.sleep(retry_delay)
|
|
76
|
+
|
|
77
|
+
finally:
|
|
78
|
+
if 'writer' in locals():
|
|
79
|
+
writer.close()
|
|
80
|
+
await writer.wait_closed()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
async def sync(self, stx: Optional[str] = None) -> AsyncGenerator[str, None]:
|
|
84
|
+
full_url = f"wss://{self.network}/sync/{stx}"
|
|
85
|
+
auth_payload = {
|
|
86
|
+
"host": self.host,
|
|
87
|
+
"password": self.password,
|
|
88
|
+
"synapse": self.synapse,
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
while True:
|
|
92
|
+
try:
|
|
93
|
+
async with websockets.connect(full_url) as ws:
|
|
94
|
+
await ws.send(json.dumps(auth_payload))
|
|
95
|
+
print("Connected to WebSocket.")
|
|
96
|
+
|
|
97
|
+
while True:
|
|
98
|
+
try:
|
|
99
|
+
raw_operation = await ws.recv()
|
|
100
|
+
operation = json.loads(raw_operation)
|
|
101
|
+
yield operation
|
|
102
|
+
|
|
103
|
+
except asyncio.TimeoutError:
|
|
104
|
+
print("No data received. Continuing...")
|
|
105
|
+
except websockets.exceptions.ConnectionClosedError as e:
|
|
106
|
+
print(f"Connection closed with error: {e}. Reconnecting...")
|
|
107
|
+
break
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print(f"Unexpected error in recv loop: {e}")
|
|
110
|
+
break
|
|
111
|
+
|
|
112
|
+
except websockets.exceptions.WebSocketException as e:
|
|
113
|
+
print(f"WebSocket error occurred: {e}. Retrying in 5 seconds...")
|
|
114
|
+
except Exception as e:
|
|
115
|
+
print(f"General error occurred: {e}. Retrying in 5 seconds...")
|
|
116
|
+
|
|
117
|
+
await asyncio.sleep(3)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
async def create_tx(self, descr: str, key_values: dict, stx: str, label: str, partners: list):
|
|
121
|
+
url = f"https://{self.network}/api/create_tx"
|
|
122
|
+
|
|
123
|
+
TX = {
|
|
124
|
+
"descr": descr,
|
|
125
|
+
"key_values": key_values,
|
|
126
|
+
"stx": stx,
|
|
127
|
+
"label": label,
|
|
128
|
+
"partners": partners,
|
|
129
|
+
"cell": self.to_dict()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async with aiohttp.ClientSession() as session:
|
|
133
|
+
try:
|
|
134
|
+
async with session.post(url, json=TX) as response:
|
|
135
|
+
response.raise_for_status()
|
|
136
|
+
data = await response.json()
|
|
137
|
+
return data["txID"]
|
|
138
|
+
|
|
139
|
+
except aiohttp.ClientError as e:
|
|
140
|
+
print(f"Error sending request: {e}")
|
|
141
|
+
except Exception as e:
|
|
142
|
+
print(f"Unexpected error: {e}")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
async def delete_tx(self, txID: str):
|
|
146
|
+
url = f"https://{self.network}/api/delete_tx"
|
|
147
|
+
|
|
148
|
+
TX = {
|
|
149
|
+
"txID": txID,
|
|
150
|
+
"cell": self.to_dict()
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async with aiohttp.ClientSession() as session:
|
|
154
|
+
try:
|
|
155
|
+
async with session.post(url, json=TX) as response:
|
|
156
|
+
response.raise_for_status()
|
|
157
|
+
data = await response.json()
|
|
158
|
+
print(f"Response from Neuronum: {data}")
|
|
159
|
+
return data
|
|
160
|
+
|
|
161
|
+
except aiohttp.ClientError as e:
|
|
162
|
+
print(f"Error sending request: {e}")
|
|
163
|
+
except Exception as e:
|
|
164
|
+
print(f"Unexpected error: {e}")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
async def activate_tx(self, txID: str, data: dict):
|
|
168
|
+
url = f"https://{self.network}/api/activate_tx/{txID}"
|
|
169
|
+
TX = {
|
|
170
|
+
"data": data,
|
|
171
|
+
"cell": self.to_dict()
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async with aiohttp.ClientSession() as session:
|
|
175
|
+
try:
|
|
176
|
+
async with session.post(url, json=TX) as response:
|
|
177
|
+
response.raise_for_status()
|
|
178
|
+
data = await response.json()
|
|
179
|
+
if data.get("success") == True:
|
|
180
|
+
if "json" in data.get("response"):
|
|
181
|
+
return data.get("response").get("json")
|
|
182
|
+
elif "html" in data.get("response"):
|
|
183
|
+
return "Info: HTML response available. Please activate TX in browser."
|
|
184
|
+
else:
|
|
185
|
+
return "Info: Response received but contains no usable content."
|
|
186
|
+
else:
|
|
187
|
+
print(data["success"], data["message"])
|
|
188
|
+
|
|
189
|
+
except aiohttp.ClientError as e:
|
|
190
|
+
print(f"Error sending request: {e}")
|
|
191
|
+
except Exception as e:
|
|
192
|
+
print(f"Unexpected error: {e}")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
async def tx_response(self, txID: str, client: str, data: dict):
|
|
196
|
+
url = f"https://{self.network}/api/tx_response/{txID}"
|
|
197
|
+
|
|
198
|
+
tx_response = {
|
|
199
|
+
"client": client,
|
|
200
|
+
"data": data,
|
|
201
|
+
"cell": self.to_dict()
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async with aiohttp.ClientSession() as session:
|
|
205
|
+
try:
|
|
206
|
+
for _ in range(2):
|
|
207
|
+
async with session.post(url, json=tx_response) as response:
|
|
208
|
+
response.raise_for_status()
|
|
209
|
+
data = await response.json()
|
|
210
|
+
print(data["message"])
|
|
211
|
+
|
|
212
|
+
except aiohttp.ClientError as e:
|
|
213
|
+
print(f"Error sending request: {e}")
|
|
214
|
+
except Exception as e:
|
|
215
|
+
print(f"Unexpected error: {e}")
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
async def create_ctx(self, descr: str, partners: list):
|
|
219
|
+
url = f"https://{self.network}/api/create_ctx"
|
|
220
|
+
|
|
221
|
+
CTX = {
|
|
222
|
+
"descr": descr,
|
|
223
|
+
"partners": partners,
|
|
224
|
+
"cell": self.to_dict()
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async with aiohttp.ClientSession() as session:
|
|
228
|
+
try:
|
|
229
|
+
async with session.post(url, json=CTX) as response:
|
|
230
|
+
response.raise_for_status()
|
|
231
|
+
data = await response.json()
|
|
232
|
+
return data["ctxID"]
|
|
233
|
+
|
|
234
|
+
except aiohttp.ClientError as e:
|
|
235
|
+
print(f"Error sending request: {e}")
|
|
236
|
+
except Exception as e:
|
|
237
|
+
print(f"Unexpected error: {e}")
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
async def delete_ctx(self, ctxID: str):
|
|
241
|
+
url = f"https://{self.network}/api/delete_ctx"
|
|
242
|
+
|
|
243
|
+
CTX = {
|
|
244
|
+
"ctxID": ctxID,
|
|
245
|
+
"cell": self.to_dict()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async with aiohttp.ClientSession() as session:
|
|
249
|
+
try:
|
|
250
|
+
async with session.post(url, json=CTX) as response:
|
|
251
|
+
response.raise_for_status()
|
|
252
|
+
data = await response.json()
|
|
253
|
+
print(f"Response from Neuronum: {data}")
|
|
254
|
+
return data
|
|
255
|
+
|
|
256
|
+
except aiohttp.ClientError as e:
|
|
257
|
+
print(f"Error sending request: {e}")
|
|
258
|
+
except Exception as e:
|
|
259
|
+
print(f"Unexpected error: {e}")
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
async def create_stx(self, descr: str, partners: list):
|
|
263
|
+
url = f"https://{self.network}/api/create_stx"
|
|
264
|
+
|
|
265
|
+
STX = {
|
|
266
|
+
"descr": descr,
|
|
267
|
+
"partners": partners,
|
|
268
|
+
"cell": self.to_dict()
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async with aiohttp.ClientSession() as session:
|
|
272
|
+
try:
|
|
273
|
+
async with session.post(url, json=STX) as response:
|
|
274
|
+
response.raise_for_status()
|
|
275
|
+
data = await response.json()
|
|
276
|
+
return data["stxID"]
|
|
277
|
+
|
|
278
|
+
except aiohttp.ClientError as e:
|
|
279
|
+
print(f"Error sending request: {e}")
|
|
280
|
+
except Exception as e:
|
|
281
|
+
print(f"Unexpected error: {e}")
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
async def delete_stx(self, stxID: str):
|
|
285
|
+
url = f"https://{self.network}/api/delete_stx"
|
|
286
|
+
|
|
287
|
+
STX = {
|
|
288
|
+
"stxID": stxID,
|
|
289
|
+
"cell": self.to_dict()
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async with aiohttp.ClientSession() as session:
|
|
293
|
+
try:
|
|
294
|
+
async with session.post(url, json=STX) as response:
|
|
295
|
+
response.raise_for_status()
|
|
296
|
+
data = await response.json()
|
|
297
|
+
print(f"Response from Neuronum: {data}")
|
|
298
|
+
return data
|
|
299
|
+
|
|
300
|
+
except aiohttp.ClientError as e:
|
|
301
|
+
print(f"Error sending request: {e}")
|
|
302
|
+
except Exception as e:
|
|
303
|
+
print(f"Unexpected error: {e}")
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
async def list_cells(self):
|
|
307
|
+
full_url = f"https://{self.network}/api/list_cells"
|
|
308
|
+
|
|
309
|
+
list_cells_payload = {
|
|
310
|
+
"cell": self.to_dict()
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async with aiohttp.ClientSession() as session:
|
|
314
|
+
try:
|
|
315
|
+
async with session.get(full_url, json=list_cells_payload) as response:
|
|
316
|
+
response.raise_for_status()
|
|
317
|
+
data = await response.json()
|
|
318
|
+
return data.get("Cells", [])
|
|
319
|
+
|
|
320
|
+
except aiohttp.ClientError as e:
|
|
321
|
+
print(f"Error sending request: {e}")
|
|
322
|
+
except Exception as e:
|
|
323
|
+
print(f"Unexpected error: {e}")
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
async def list_tx(self):
|
|
327
|
+
full_url = f"https://{self.network}/api/list_tx"
|
|
328
|
+
|
|
329
|
+
list_tx_payload = {
|
|
330
|
+
"cell": self.to_dict()
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
async with aiohttp.ClientSession() as session:
|
|
334
|
+
try:
|
|
335
|
+
async with session.get(full_url, json=list_tx_payload) as response:
|
|
336
|
+
response.raise_for_status()
|
|
337
|
+
data = await response.json()
|
|
338
|
+
return data.get("Transmitters", [])
|
|
339
|
+
|
|
340
|
+
except aiohttp.ClientError as e:
|
|
341
|
+
print(f"Error sending request: {e}")
|
|
342
|
+
except Exception as e:
|
|
343
|
+
print(f"Unexpected error: {e}")
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
async def list_ctx(self):
|
|
347
|
+
full_url = f"https://{self.network}/api/list_ctx"
|
|
348
|
+
|
|
349
|
+
list_ctx_payload = {
|
|
350
|
+
"cell": self.to_dict()
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
async with aiohttp.ClientSession() as session:
|
|
354
|
+
try:
|
|
355
|
+
async with session.get(full_url, json=list_ctx_payload) as response:
|
|
356
|
+
response.raise_for_status()
|
|
357
|
+
data = await response.json()
|
|
358
|
+
return data.get("Circuits", [])
|
|
359
|
+
|
|
360
|
+
except aiohttp.ClientError as e:
|
|
361
|
+
print(f"Error sending request: {e}")
|
|
362
|
+
except Exception as e:
|
|
363
|
+
print(f"Unexpected error: {e}")
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
async def list_stx(self):
|
|
367
|
+
full_url = f"https://{self.network}/api/list_stx"
|
|
368
|
+
|
|
369
|
+
list_stx_payload = {
|
|
370
|
+
"cell": self.to_dict()
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
async with aiohttp.ClientSession() as session:
|
|
374
|
+
try:
|
|
375
|
+
async with session.get(full_url, json=list_stx_payload) as response:
|
|
376
|
+
response.raise_for_status()
|
|
377
|
+
data = await response.json()
|
|
378
|
+
return data.get("Streams", [])
|
|
379
|
+
|
|
380
|
+
except aiohttp.ClientError as e:
|
|
381
|
+
print(f"Error sending request: {e}")
|
|
382
|
+
except Exception as e:
|
|
383
|
+
print(f"Unexpected error: {e}")
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
async def list_nodes(self):
|
|
387
|
+
full_url = f"https://{self.network}/api/list_nodes"
|
|
388
|
+
|
|
389
|
+
list_nodes_payload = {
|
|
390
|
+
"cell": self.to_dict()
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
async with aiohttp.ClientSession() as session:
|
|
394
|
+
try:
|
|
395
|
+
async with session.get(full_url, json=list_nodes_payload) as response:
|
|
396
|
+
response.raise_for_status()
|
|
397
|
+
data = await response.json()
|
|
398
|
+
return data.get("Nodes", [])
|
|
399
|
+
|
|
400
|
+
except aiohttp.ClientError as e:
|
|
401
|
+
print(f"Error sending request: {e}")
|
|
402
|
+
except Exception as e:
|
|
403
|
+
print(f"Unexpected error: {e}")
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
async def store(self, label: str, data: dict, ctx: Optional[str] = None):
|
|
407
|
+
full_url = f"https://{self.network}/api/store_in_ctx/{ctx}" if ctx else f"https://{self.network}/api/store"
|
|
408
|
+
|
|
409
|
+
store_payload = {
|
|
410
|
+
"label": label,
|
|
411
|
+
"data": data,
|
|
412
|
+
"cell": self.to_dict()
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async with aiohttp.ClientSession() as session:
|
|
416
|
+
try:
|
|
417
|
+
async with session.post(full_url, json=store_payload) as response:
|
|
418
|
+
response.raise_for_status()
|
|
419
|
+
data = await response.json()
|
|
420
|
+
print(f"Response from Neuronum: {data}")
|
|
421
|
+
return data
|
|
422
|
+
|
|
423
|
+
except aiohttp.ClientError as e:
|
|
424
|
+
print(f"Error sending request: {e}")
|
|
425
|
+
except Exception as e:
|
|
426
|
+
print(f"Unexpected error: {e}")
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
async def load(self, label: str, ctx: Optional[str] = None):
|
|
430
|
+
full_url = f"https://{self.network}/api/load_from_ctx/{ctx}" if ctx else f"https://{self.network}/api/load"
|
|
431
|
+
|
|
432
|
+
load_payload = {
|
|
433
|
+
"label": label,
|
|
434
|
+
"cell": self.to_dict()
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
async with aiohttp.ClientSession() as session:
|
|
438
|
+
try:
|
|
439
|
+
async with session.post(full_url, json=load_payload) as response:
|
|
440
|
+
response.raise_for_status()
|
|
441
|
+
data = await response.json()
|
|
442
|
+
return data
|
|
443
|
+
|
|
444
|
+
except aiohttp.ClientError as e:
|
|
445
|
+
print(f"Error sending request: {e}")
|
|
446
|
+
except Exception as e:
|
|
447
|
+
print(f"Unexpected error: {e}")
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
async def delete(self, label: str, ctx: Optional[str] = None):
|
|
451
|
+
full_url = f"https://{self.network}/api/delete_from_ctx/{ctx}" if ctx else f"https://{self.network}/api/delete"
|
|
452
|
+
|
|
453
|
+
delete_payload = {
|
|
454
|
+
"label": label,
|
|
455
|
+
"cell": self.to_dict()
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
async with aiohttp.ClientSession() as session:
|
|
459
|
+
try:
|
|
460
|
+
async with session.post(full_url, json=delete_payload) as response:
|
|
461
|
+
response.raise_for_status()
|
|
462
|
+
data = await response.json()
|
|
463
|
+
print(f"Response from Neuronum: {data}")
|
|
464
|
+
return data
|
|
465
|
+
|
|
466
|
+
except aiohttp.ClientError as e:
|
|
467
|
+
print(f"Error sending request: {e}")
|
|
468
|
+
except Exception as e:
|
|
469
|
+
print(f"Unexpected error: {e}")
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
async def clear(self, ctx: Optional[str] = None):
|
|
473
|
+
full_url = f"https://{self.network}/api/clear_ctx/{ctx}" if ctx else f"https://{self.network}/api/clear"
|
|
474
|
+
|
|
475
|
+
clear_payload = {
|
|
476
|
+
"cell": self.to_dict()
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async with aiohttp.ClientSession() as session:
|
|
480
|
+
try:
|
|
481
|
+
async with session.post(full_url, json=clear_payload) as response:
|
|
482
|
+
response.raise_for_status()
|
|
483
|
+
data = await response.json()
|
|
484
|
+
print(f"Response from Neuronum: {data}")
|
|
485
|
+
return data
|
|
486
|
+
|
|
487
|
+
except aiohttp.ClientError as e:
|
|
488
|
+
print(f"Error sending request: {e}")
|
|
489
|
+
except Exception as e:
|
|
490
|
+
print(f"Unexpected error: {e}")
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
async def notify(self, receiver: str, title: str, message: str):
|
|
494
|
+
full_url = f"https://{self.network}/api/notify"
|
|
495
|
+
|
|
496
|
+
notify_payload = {
|
|
497
|
+
"receiver": receiver,
|
|
498
|
+
"notification": {
|
|
499
|
+
"title": title,
|
|
500
|
+
"message": message
|
|
501
|
+
},
|
|
502
|
+
"cell": self.to_dict()
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async with aiohttp.ClientSession() as session:
|
|
506
|
+
try:
|
|
507
|
+
async with session.post(full_url, json=notify_payload) as response:
|
|
508
|
+
response.raise_for_status()
|
|
509
|
+
data = await response.json()
|
|
510
|
+
print(f"Notification sent successfully: {data}")
|
|
511
|
+
return data
|
|
512
|
+
|
|
513
|
+
except aiohttp.ClientError as e:
|
|
514
|
+
print(f"HTTP error while sending notification: {e}")
|
|
515
|
+
except Exception as e:
|
|
516
|
+
print(f"Unexpected error: {e}")
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
__all__ = ['Cell']
|