2
0
mirror of https://github.com/ComradCollective/Comrad synced 2024-11-11 13:10:45 +00:00
Comrad/p2p/api.py

750 lines
23 KiB
Python
Raw Normal View History

2020-08-19 13:01:37 +00:00
import os,time,sys,logging
2020-08-17 13:33:26 +00:00
from pathlib import Path
2020-08-20 00:34:14 +00:00
import asyncio,time
2020-08-19 13:01:37 +00:00
# handler = logging.StreamHandler()
# formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
# handler.setFormatter(formatter)
# logger = logging.getLogger(__file__)
# logger.addHandler(handler)
# logger.setLevel(logging.DEBUG)
sys.path.append('../p2p')
# logger.info(os.getcwd(), sys.path)
2020-08-20 15:48:08 +00:00
BSEP=b'\n\n'
BSEP2=b'\t\n'
BSEP3=b'\r\r'
2020-08-19 13:01:37 +00:00
2020-08-19 12:06:44 +00:00
try:
from .crypto import *
from .p2p import *
from .kad import *
2020-08-20 15:48:08 +00:00
except (ModuleNotFoundError,ImportError):
2020-08-19 12:06:44 +00:00
from crypto import *
from p2p import *
2020-08-20 15:48:08 +00:00
from kad import *
2020-08-17 20:40:48 +00:00
from pathlib import Path
from functools import partial
2020-08-17 13:33:26 +00:00
# works better with tor?
import json
jsonify = json.dumps
2020-08-19 10:29:56 +00:00
2020-08-17 13:33:26 +00:00
# Start server
DEBUG = True
UPLOAD_DIR = 'uploads/'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
2020-08-19 10:29:56 +00:00
2020-08-18 15:14:19 +00:00
# PORT_SPEAK = 8468
2020-08-19 14:07:12 +00:00
PORT_LISTEN = 5639
2020-08-17 13:33:26 +00:00
# Api Functions
from threading import Thread
def start_selfless_thread():
async def _go():
loop=asyncio.get_event_loop()
return boot_selfless_node(port=PORT_SPEAK, loop=loop)
return asyncio.run(_go())
2020-08-17 13:33:26 +00:00
2020-08-19 12:06:44 +00:00
async def _getdb(self=None,port=PORT_LISTEN):
if self: self.log('starting server..')
import os
2020-08-20 15:48:08 +00:00
if self: self.log(os.getcwd())
2020-08-20 21:45:30 +00:00
node = KadServer(storage=HalfForgetfulStorage()) #fn='../p2p/data.db',log=(self.log if self else print)))
2020-08-19 11:30:23 +00:00
2020-08-19 12:06:44 +00:00
if self: self.log('listening..')
2020-08-19 11:30:23 +00:00
await node.listen(port)
2020-08-19 12:06:44 +00:00
if self: self.log('bootstrapping server..')
2020-08-19 11:30:23 +00:00
await node.bootstrap(NODES_PRIME)
return node
2020-08-19 12:06:44 +00:00
def logg(x):
print(x)
2020-08-17 16:23:40 +00:00
class Api(object):
2020-08-19 12:06:44 +00:00
def __init__(self,app = None):
2020-08-19 10:29:56 +00:00
self.app=app
2020-08-19 12:06:44 +00:00
self.app_storage = self.app.store if app else {}
self.log = self.app.log if app else logg
2020-08-18 17:25:15 +00:00
2020-08-19 10:29:56 +00:00
# self.log('starting selfless daemon...')
2020-08-18 15:00:14 +00:00
# self.selfless = Thread(target=start_selfless_thread)
# self.selfless.daemon = True
# self.selfless.start()
2020-08-19 10:29:56 +00:00
# connect?
2020-08-19 13:01:37 +00:00
#self._node=self.connect()
2020-08-17 16:23:40 +00:00
pass
2020-08-20 20:08:47 +00:00
async def connect_forever(self,port=PORT_LISTEN):
2020-08-19 14:07:12 +00:00
try:
i = 0
2020-08-20 20:08:47 +00:00
self._node = await self.connect(port=port)
2020-08-19 14:07:12 +00:00
while True:
2020-08-20 21:45:30 +00:00
#self.log(i)
2020-08-20 18:36:04 +00:00
if not i%10: self.log(f'Node status (tick {i}): {self._node}')
2020-08-20 21:45:30 +00:00
if i and not i%60: await self.flush()
2020-08-19 14:07:12 +00:00
# # get some sleep
# if self.root.ids.btn1.state != 'down' and i >= 2:
# i = 0
# self.log('Yawn, getting tired. Going to sleep')
# self.root.ids.btn1.trigger_action()
2020-08-20 01:39:26 +00:00
i += 1
2020-08-20 21:45:30 +00:00
await asyncio.sleep(1)
2020-08-19 19:33:25 +00:00
# pass
2020-08-19 14:07:12 +00:00
except asyncio.CancelledError as e:
2020-08-20 09:51:57 +00:00
self.log('P2P node cancelled', e)
2020-08-19 14:07:12 +00:00
finally:
# when canceled, print that it finished
2020-08-20 09:51:57 +00:00
self.log('P2P node shutting down')
2020-08-19 14:07:12 +00:00
@property
async def node(self):
if not hasattr(self,'_node'):
self._node=await self.connect()
return self._node
async def connect(self,port=PORT_LISTEN):
self.log('connecting...')
return await _getdb(self,port)
2020-08-20 18:26:33 +00:00
async def get(self,key_or_keys,get_last=True):
2020-08-17 16:23:40 +00:00
async def _get():
2020-08-19 14:07:12 +00:00
node=await self.node
2020-08-20 21:10:59 +00:00
res=None
2020-08-17 20:40:48 +00:00
if type(key_or_keys) in {list,tuple,dict}:
keys = key_or_keys
2020-08-20 18:26:33 +00:00
tasks=[]
for key in keys:
2020-08-20 21:10:59 +00:00
val = await node.get(key)
task = self.decode_data(val)
tasks.append(task)
2020-08-20 18:26:33 +00:00
res = await asyncio.gather(*tasks)
else:
2020-08-20 21:10:59 +00:00
key=key_or_keys
val = await node.get(key)
res = await self.decode_data(val)
2020-08-17 20:40:48 +00:00
2020-08-20 21:50:58 +00:00
# self.log(f'_get({key_or_keys}) --> {res}')
2020-08-20 21:10:59 +00:00
return res
2020-08-19 14:07:12 +00:00
return await _get()
2020-08-20 00:34:14 +00:00
2020-08-20 15:09:43 +00:00
def encode_data(self,val,sep=BSEP,sep2=BSEP2,do_encrypt=True,receiver_pubkey=None):
2020-08-20 00:34:14 +00:00
"""
What do we want to store with
2020-08-20 15:09:43 +00:00
1) [Encrypted payload:]
1) Timestamp
2) Public key of sender
3) Public key of recipient
4) AES-encrypted Value
2) [Decryption tools]
1) AES-decryption key
2) AES decryption IV value
5) Signature of value by author
2020-08-20 00:34:14 +00:00
"""
2020-08-20 08:55:50 +00:00
import time
2020-08-20 00:34:14 +00:00
timestamp=time.time()
2020-08-20 15:09:43 +00:00
# convert val to bytes
if type(val)!=bytes: val = bytes(val,'utf-8')
value_bytes=base64.b64encode(val)
2020-08-20 01:39:26 +00:00
2020-08-20 15:09:43 +00:00
# sign
signature = sign(value_bytes, self.private_key)
sender_pubkey_b = serialize_pubkey(self.public_key)
2020-08-20 00:34:14 +00:00
2020-08-20 15:09:43 +00:00
# Verify!
authentic = verify_signature(signature, value_bytes, self.public_key)
if not authentic:
self.log('message is inauthentic for set??',authentic)
return None
2020-08-20 00:34:14 +00:00
2020-08-20 15:09:43 +00:00
# encrypt?
if not receiver_pubkey: receiver_pubkey=self.public_key_global
2020-08-20 08:55:50 +00:00
receiver_pubkey_b = serialize_pubkey(receiver_pubkey)
2020-08-20 15:09:43 +00:00
time_b=str(timestamp).encode()
msg=value_bytes
2020-08-20 08:55:50 +00:00
2020-08-20 15:09:43 +00:00
# whole binary package
WDV = [
2020-08-20 08:55:50 +00:00
time_b,
sender_pubkey_b,
2020-08-20 15:09:43 +00:00
receiver_pubkey_b,
msg,
2020-08-20 08:55:50 +00:00
signature
2020-08-20 15:09:43 +00:00
]
payload = sep2.join(WDV)
res = aes_rsa_encrypt(payload,receiver_pubkey)
if res is None: return None
payload_encr_aes, payload_encr_aes_key, payload_encr_aes_iv = res
decryption_tools = sep2.join([
payload_encr_aes_key,
payload_encr_aes_iv
2020-08-20 08:55:50 +00:00
])
2020-08-20 15:09:43 +00:00
final_packet = sep.join([
payload_encr_aes,
decryption_tools
])
return final_packet
2020-08-20 00:34:14 +00:00
2020-08-20 15:09:43 +00:00
async def decode_data(self,entire_packet,sep=BSEP,private_key=None,sep2=BSEP2):
if entire_packet is None: return entire_packet
#entire_packet = base64.b64decode(entire_packet)
2020-08-20 08:55:50 +00:00
2020-08-20 15:09:43 +00:00
# get data
encrypted_payload, decryption_tools = entire_packet.split(sep)
decryption_tools=decryption_tools.split(sep2)
# ### FIRST LINE OF PROTECTION
# # is the receiver's public id in our list of public IDs?
# to_pub = load_pubkey(to_pub_b)
# oktogo=False
# CORRECT_PUB_KEY=None
# CORRECT_PRIV_KEY=None
# for privkey,pubkey in self.keys():
# if pubkey.public_numbers() == to_pub.public_numbers():
# oktogo=True
# CORRECT_PUB_KEY = pubkey
# CORRECT_PRIV_KEY = privkey
# break
# if not oktogo: return None
2020-08-20 01:39:26 +00:00
2020-08-20 15:09:43 +00:00
### SECOND LINE OF PROTECTION
# first try to decrypt sender to see if we have access to this
# def _decrypt_aes_rsa(args):
# val_encr,val_encr_key,iv = args
# val = aes_rsa_decrypt(val_encr,val_encr_key,iv,CORRECT_PRIV_KEY)
# return val
# from_pub_decr = _decrypt_rsa(*sender_encr)
# if not from_pub_decr: return None
# from_pub = load_pubkey(from_pub_b)
2020-08-20 08:55:50 +00:00
2020-08-20 01:39:26 +00:00
2020-08-20 15:09:43 +00:00
### NEW FIRST LINE: Try to decrypt!
val=None
for keyname,privkey,pubkey in self.keys():
try:
val = aes_rsa_decrypt(encrypted_payload,privkey,*decryption_tools)
#self.log('decrypted =',val)
break
except ValueError as e:
self.log(keyname,'did not work!') #,privkey,pubkey)
pass
if not val:
self.log('Content not intended for us')
return None
#stop
### THIRD LINE: SIGNATURE VERIFICATION
# can we decrypt signature?
val_array = val.split(sep2)
2020-08-20 21:50:58 +00:00
# self.log('val_array =',val_array)
2020-08-20 15:09:43 +00:00
time_b,sender_pubkey_b,receiver_pubkey_b,msg,signature = val_array
if not signature: return None
sender_pubkey=load_pubkey(sender_pubkey_b)
authentic = verify_signature(signature,msg,sender_pubkey)
2020-08-20 01:39:26 +00:00
if not authentic:
self.log('inauthentic message!')
2020-08-20 15:09:43 +00:00
return None
2020-08-20 01:39:26 +00:00
2020-08-20 15:09:43 +00:00
# ### FOURTH LINE: CONTENT ENCRYPTION
# if private_key is None:
# private_key=self.private_key_global
2020-08-20 09:51:57 +00:00
2020-08-20 15:09:43 +00:00
# val_encr = base64.b64decode(val_encr)
# val_encr_key = base64.b64decode(val_encr_key)
2020-08-20 09:51:57 +00:00
# self.log(f"""decrypting
# val_encr = {val_encr}
# val_encr_key = {val_encr_key}
# iv = {iv}
# private_key = {private_key}
# """)
2020-08-20 15:09:43 +00:00
2020-08-20 09:51:57 +00:00
2020-08-20 15:09:43 +00:00
# val = _decrypt_aes()
2020-08-20 08:55:50 +00:00
# self.log('val after decryption = ',val)
2020-08-20 15:09:43 +00:00
# valdec = base64.b64decode(val)
2020-08-20 11:48:26 +00:00
2020-08-20 08:55:50 +00:00
WDV={
'time':float(time_b.decode()),
2020-08-20 15:09:43 +00:00
'val':base64.b64decode(msg).decode(),
'to':receiver_pubkey_b,
'from':sender_pubkey_b,
2020-08-20 08:55:50 +00:00
'sign':signature
}
2020-08-20 21:50:58 +00:00
# self.log('GOT WDV:',WDV)
2020-08-20 08:55:50 +00:00
return WDV
#,signature
2020-08-20 01:39:26 +00:00
2020-08-19 14:27:12 +00:00
2020-08-19 14:07:12 +00:00
async def set(self,key_or_keys,value_or_values):
2020-08-19 14:27:12 +00:00
async def _set():
2020-08-19 11:14:52 +00:00
# self.log('async _set()',self.node)
2020-08-19 11:30:23 +00:00
# node=self.node
2020-08-19 14:07:12 +00:00
#node=await _getdb(self)
node=await self.node
2020-08-19 13:01:37 +00:00
2020-08-17 20:40:48 +00:00
if type(key_or_keys) in {list,tuple,dict}:
keys = key_or_keys
values = value_or_values
assert len(keys)==len(values)
2020-08-20 15:09:43 +00:00
res = await asyncio.gather(*[node.set(key,self.encode_data(value)) for key,value in zip(keys,values)])
2020-08-19 10:29:56 +00:00
# self.log('RES?',res)
2020-08-17 20:40:48 +00:00
else:
key = key_or_keys
value = value_or_values
2020-08-20 17:43:28 +00:00
res = await node.set(key,self.encode_data(value))
2020-08-17 20:40:48 +00:00
2020-08-19 14:07:12 +00:00
#node.stop()
2020-08-17 20:40:48 +00:00
return res
2020-08-18 17:25:15 +00:00
2020-08-19 14:27:12 +00:00
return await _set()
2020-08-18 17:25:15 +00:00
2020-08-20 18:26:33 +00:00
async def get_json(self,key_or_keys,get_last=True):
2020-08-20 08:55:50 +00:00
2020-08-20 21:50:58 +00:00
# def jsonize(entry):
2020-08-20 11:48:26 +00:00
self.log('jsonize!',entry)
2020-08-20 17:43:28 +00:00
if not entry: return entry
2020-08-20 08:55:50 +00:00
if not 'val' in entry: return entry
val=entry['val']
2020-08-20 11:48:26 +00:00
try:
dat=json.loads(val) if val else val
except UnicodeDecodeError:
dat=val
2020-08-20 21:50:58 +00:00
# self.log('dat??',dat)
2020-08-20 08:55:50 +00:00
entry['val']=dat
return entry
2020-08-20 18:26:33 +00:00
def jsonize_res(res):
# parse differently?
if type(res)==list:
jsonl=[jsonize(entry) for entry in res]
return jsonl
else:
entry = res
return jsonize(entry)
# if key_or_keys.startsiwth('/post/'):
res = await self.get(key_or_keys,get_last=get_last)
self.log('get_json() got',res)
if not res: return None
2020-08-20 21:10:59 +00:00
return jsonize_res(res)
2020-08-20 18:26:33 +00:00
2020-08-19 13:01:37 +00:00
2020-08-17 20:40:48 +00:00
2020-08-19 14:07:12 +00:00
async def set_json(self,key,value):
2020-08-17 20:40:48 +00:00
value_json = jsonify(value)
2020-08-19 10:29:56 +00:00
# self.log('OH NO!',sys.getsizeof(value_json))
2020-08-19 14:27:12 +00:00
return await self.set(key,value_json)
2020-08-17 16:23:40 +00:00
2020-08-19 19:33:25 +00:00
async def has(self,key):
val=await self.get(key)
return val is not None
2020-08-17 16:23:40 +00:00
## PERSONS
2020-08-19 19:33:25 +00:00
async def get_person(self,username):
2020-08-20 17:43:28 +00:00
return await self.get_json_val('/person/'+username)
2020-08-17 16:23:40 +00:00
2020-08-20 08:55:50 +00:00
async def set_person(self,username,pem_public_key):
# pem_public_key = save_public_key(public_key,return_instead=True)
obj = {'name':username, 'public_key':pem_public_key}
2020-08-19 19:33:25 +00:00
await self.set_json('/person/'+username,obj)
2020-08-17 16:23:40 +00:00
## Register
2020-08-19 19:33:25 +00:00
async def register(self,name,passkey):
if not (name and passkey): return {'error':'Name and password needed'}
person = await self.get_person(name)
if person is not None: return {'error':'Username already exists'}
2020-08-17 16:23:40 +00:00
2020-08-20 08:55:50 +00:00
self._private_key = private_key = generate_rsa_key()
# self._public_key = public_key = self.private_key.public_key()
pem_private_key = serialize_privkey(self.private_key, password=passkey)# save_private_key(private_key,password=passkey,return_instead=True)
#pem_public_key = save_public_key(public_key,return_instead=True)
pem_public_key = serialize_pubkey(self.public_key)
await self.set_person(name,pem_public_key.decode())
2020-08-17 16:23:40 +00:00
self.app_storage.put('_keys',
2020-08-20 08:55:50 +00:00
private=pem_private_key.decode(),
public=pem_public_key.decode()) #(private_key,password=passkey)
2020-08-17 16:23:40 +00:00
return {'success':'Account created', 'username':name}
2020-08-20 01:39:26 +00:00
2020-08-17 16:23:40 +00:00
def load_private_key(self,password):
2020-08-19 23:26:25 +00:00
if not self.app_storage.exists('_keys'): return {'error':'No login keys present on this device'}
2020-08-17 16:23:40 +00:00
pem_private_key=self.app_storage.get('_keys').get('private')
2020-08-20 08:55:50 +00:00
self.log('my private key ====',pem_private_key)
2020-08-17 16:23:40 +00:00
try:
2020-08-20 08:55:50 +00:00
return {'success':load_privkey(pem_private_key,password)}
2020-08-17 16:23:40 +00:00
except ValueError as e:
2020-08-19 10:29:56 +00:00
self.log('!!',e)
2020-08-19 20:15:38 +00:00
return {'error':'Incorrect password'}
2020-08-17 16:23:40 +00:00
## LOGIN
2020-08-19 19:33:25 +00:00
async def login(self,name,passkey):
2020-08-17 16:23:40 +00:00
# verify input
if not (name and passkey):
return {'error':'Name and password required'}
# try to load private key
2020-08-19 19:33:25 +00:00
private_key_dat = self.load_private_key(passkey)
if 'error' in private_key_dat:
return {'error':private_key_dat['error']}
if not 'success' in private_key_dat:
return {'error':'Incorrect password?'}
2020-08-20 00:34:14 +00:00
self._private_key = private_key = private_key_dat['success']
2020-08-17 16:23:40 +00:00
# see if user exists
2020-08-19 19:33:25 +00:00
person = await self.get_person(name)
2020-08-19 10:29:56 +00:00
self.log(person)
2020-08-17 16:23:40 +00:00
if person is None:
return {'error':'Login failed'}
# verify keys
2020-08-20 09:51:57 +00:00
self.log('got person =',person)
2020-08-17 16:23:40 +00:00
person_public_key_pem = person['public_key']
2020-08-20 08:55:50 +00:00
public_key = load_pubkey(person_public_key_pem) #load_public_key(person_public_key_pem.encode())
2020-08-20 00:34:14 +00:00
self._public_key = real_public_key = private_key.public_key()
2020-08-17 16:23:40 +00:00
#log('PUBLIC',public_key.public_numbers())
#log('REAL PUBLIC',real_public_key.public_numbers())
if public_key.public_numbers() != real_public_key.public_numbers():
2020-08-19 19:33:25 +00:00
return {'error':'Keys do not match!'}
2020-08-17 16:23:40 +00:00
return {'success':'Login successful', 'username':name}
2020-08-20 00:34:14 +00:00
@property
def public_key(self):
if not hasattr(self,'_public_key'):
2020-08-20 08:55:50 +00:00
if not hasattr(self,'_private_key'):
self.app.root.change_screen('login')
else:
self._public_key=self.private_key.public_key()
2020-08-20 00:34:14 +00:00
return self._public_key
@property
def private_key(self):
if not hasattr(self,'_private_key'):
self.app.root.change_screen('login')
return self._private_key
2020-08-20 01:39:26 +00:00
@property
def public_key_global(self):
if not hasattr(self,'_public_key_global'):
try:
pem=self.app.store_global.get('_keys').get('public',None)
2020-08-20 09:51:57 +00:00
self.log('PEM GLOBAL = ',pem)
self._public_key_global=load_pubkey(pem.encode())
self.log('PUBKEYGLOBAL =',self._public_key_global)
2020-08-20 01:39:26 +00:00
return self._public_key_global
except ValueError as e:
self.log('!!',e)
2020-08-20 09:51:57 +00:00
else:
return self._public_key_global
2020-08-20 01:39:26 +00:00
@property
def private_key_global(self):
if not hasattr(self,'_private_key_global'):
try:
pem=self.app.store_global.get('_keys').get('private',None)
2020-08-20 09:51:57 +00:00
#self.log('PEM PRIVATE GLOBAL',pem)
self._private_key_global=load_privkey(pem.encode())
2020-08-20 01:39:26 +00:00
return self._private_key_global
except ValueError as e:
self.log('!!',e)
2020-08-20 09:51:57 +00:00
else:
return self._private_key_global
2020-08-20 15:09:43 +00:00
#@property
2020-08-20 10:02:18 +00:00
def keys(self):
2020-08-20 15:09:43 +00:00
keys= [('/channel/global',self.private_key_global,self.public_key_global)]
2020-08-20 10:02:18 +00:00
if hasattr(self,'_private_key') and hasattr(self,'_public_key'):
2020-08-20 15:09:43 +00:00
keys+=[('/channel/self',self.private_key,self.public_key)]
2020-08-20 10:02:18 +00:00
return keys
2020-08-20 01:39:26 +00:00
2020-08-19 14:07:12 +00:00
async def append_json(self,key,data):
2020-08-20 17:43:28 +00:00
sofar=await self.get_json_val(key)
2020-08-17 20:40:48 +00:00
if sofar is None: sofar = []
2020-08-20 21:10:59 +00:00
if type(sofar)!=list: sofar=[sofar]
if type(data)!=list: data=[data]
new=sofar + data
2020-08-19 14:07:12 +00:00
if await self.set_json(key, new):
2020-08-17 20:40:48 +00:00
return {'success':'Length increased to %s' % len(new)}
return {'error':'Could not append json'}
2020-08-19 19:33:25 +00:00
async def upload(self,filename,file_id=None, uri='/file/',uri_part='/part/'):
2020-08-17 20:40:48 +00:00
import sys
if not file_id: file_id = get_random_id()
part_ids = []
part_keys = []
parts=[]
PARTS=[]
buffer_size=100
2020-08-20 11:48:26 +00:00
for part in bytes_from_file(filename,chunksize=1024*2):
2020-08-17 20:40:48 +00:00
part_id = get_random_id()
part_ids.append(part_id)
part_key='/part/'+part_id
part_keys.append(part_key)
parts.append(part)
# PARTS.append(part)
2020-08-19 10:29:56 +00:00
self.log('part!:',sys.getsizeof(part))
2020-08-17 20:40:48 +00:00
#self.set(part_key,part)
if len(parts)>=buffer_size:
2020-08-19 10:29:56 +00:00
self.log('setting...')
2020-08-19 19:33:25 +00:00
await self.set(part_keys,parts)
2020-08-17 20:40:48 +00:00
part_keys=[]
PARTS+=parts
parts=[]
# set all parts
#self.set(part_keys,PARTS)
2020-08-19 10:29:56 +00:00
self.log('# parts:',len(PARTS))
2020-08-20 10:59:53 +00:00
if parts and part_keys:
await self.set(part_keys, parts)
2020-08-17 20:40:48 +00:00
# how many parts?
2020-08-19 10:29:56 +00:00
self.log('# pieces!',len(part_ids))
2020-08-17 20:40:48 +00:00
file_store = {'ext':os.path.splitext(filename)[-1][1:], 'parts':part_ids}
2020-08-19 10:29:56 +00:00
self.log('FILE STORE??',file_store)
2020-08-19 19:33:25 +00:00
await self.set_json(uri+file_id,file_store)
2020-08-17 20:40:48 +00:00
# file_store['data'].seek(0)
file_store['id']=file_id
return file_store
2020-08-17 16:23:40 +00:00
2020-08-19 19:33:25 +00:00
async def download(self,file_id):
2020-08-20 10:59:53 +00:00
self.log('file_id =',file_id)
2020-08-20 17:43:28 +00:00
file_store = await self.get_json_val('/file/'+file_id)
2020-08-20 10:59:53 +00:00
self.log('file_store =',file_store)
if file_store is None: return
2020-08-19 10:29:56 +00:00
self.log('file_store!?',file_store)
keys = ['/part/'+x for x in file_store['parts']]
2020-08-20 11:48:26 +00:00
2020-08-20 17:43:28 +00:00
#time,pieces,pub,sign = await self.get_json_val(keys)
pieces = await self.get_json_val(keys)
2020-08-20 11:48:26 +00:00
self.log('pieces = ',pieces)
file_store['parts_data']=pieces
return file_store
2020-08-20 17:43:28 +00:00
#def get_current_event_id(self):
# return self.get_json_val(self,'/current/event/id')
2020-08-20 15:48:08 +00:00
2020-08-20 17:43:28 +00:00
# def get_uri(self):
# event_id = self.get_current_event_id()
# event_id=1 if event_id is None else int(event_id)
# return f'/post/{event_id}'
2020-08-20 21:45:30 +00:00
async def flush(self):
self.log('saving back to db file...')
node = await self.node
node.storage.dump()
self.log('DONE saving back to db file...')
2020-08-20 17:43:28 +00:00
async def post(self,data,channels = ['earth'], add_profile=True):
2020-08-17 20:40:48 +00:00
post_id=get_random_id()
2020-08-19 14:07:12 +00:00
res = await self.set_json('/post/'+post_id, data)
2020-08-19 11:14:52 +00:00
self.log('Api.post() got data back from set_json():',res)
2020-08-17 13:33:26 +00:00
2020-08-19 11:14:52 +00:00
# ## add to channels
2020-08-20 17:43:28 +00:00
res = await asyncio.gather(*[
2020-08-20 21:10:59 +00:00
self.append_json(f'/posts/channel/{channel}',post_id) for channel in channels
2020-08-20 17:43:28 +00:00
])
2020-08-19 11:14:52 +00:00
# ## add to user
2020-08-19 13:01:37 +00:00
un=data.get('author')
2020-08-20 17:43:28 +00:00
if un: await self.set_json('/posts/author/'+un, post_id)
2020-08-17 13:33:26 +00:00
2020-08-17 20:40:48 +00:00
if res:
2020-08-20 21:45:30 +00:00
asyncio.create_task(self.flush())
2020-08-17 20:40:48 +00:00
return {'success':'Posted! %s' % post_id, 'post_id':post_id}
return {'error':'Post failed'}
2020-08-17 13:33:26 +00:00
2020-08-20 18:26:33 +00:00
async def get_json_val(self,uri,get_last=True):
res=await self.get_json(uri,get_last=get_last)
2020-08-20 17:43:28 +00:00
self.log('get_json_val() got',res)
2020-08-20 11:48:26 +00:00
r=None
if type(res) == dict:
2020-08-20 18:26:33 +00:00
r=res.get('val',None) if res is not None else None
2020-08-20 09:51:57 +00:00
elif type(res) == list:
2020-08-20 18:26:33 +00:00
r=[x.get('val',None) for x in res if x is not None]
2020-08-20 17:43:28 +00:00
self.log('get_json_val() giving back',r)
2020-08-20 11:48:26 +00:00
return r
2020-08-20 09:51:57 +00:00
2020-08-19 14:07:12 +00:00
async def get_post(self,post_id):
2020-08-20 17:43:28 +00:00
return await self.get_json_val(post_id)
2020-08-17 13:33:26 +00:00
2020-08-20 17:43:28 +00:00
async def get_posts(self,uri='/posts/channel/earth'):
# index = await self.get_json_val('/posts'+uri)
2020-08-20 18:26:33 +00:00
index = await self.get_json_val(uri,get_last=False)
2020-08-17 20:40:48 +00:00
if index is None: return []
2020-08-20 18:26:33 +00:00
if type(index)!=list: index=[index]
self.log('got index?',index)
index = [x for x in index if x is not None]
2020-08-20 17:43:28 +00:00
data = await self.get_json_val(['/post/'+x for x in index])
# return index
return data
2020-08-17 13:33:26 +00:00
2020-08-19 19:33:25 +00:00
## func
def bytes_from_file(filename,chunksize=8192):
with open(filename, 'rb') as f:
while True:
piece = f.read(chunksize)
if not piece:
break
yield piece
2020-08-17 13:33:26 +00:00
2020-08-17 20:40:48 +00:00
def get_random_id():
import uuid
return uuid.uuid4().hex
2020-08-17 13:33:26 +00:00
2020-08-17 20:40:48 +00:00
2020-08-19 12:06:44 +00:00
2020-08-19 13:01:37 +00:00
def test_api():
2020-08-20 15:48:08 +00:00
2020-08-19 13:01:37 +00:00
# api.set(['a','b','c'],[1,2,3])
2020-08-20 15:48:08 +00:00
async def run():
2020-08-20 16:31:17 +00:00
api = Api()
2020-08-20 15:48:08 +00:00
# await api.connect()
#await api.set_json('whattttt',{'aaaaa':12222})
#await api.set_json('whattttt',[111])
#await api.set_json('whattttt',[111])
#val = await api.get_json('whattttt')
2020-08-20 16:31:17 +00:00
server = await _getdb(api)
2020-08-20 15:48:08 +00:00
await server.set('a',1)
2020-08-20 16:31:17 +00:00
print(await server.get('a'))
await asyncio.sleep(5)
2020-08-20 15:48:08 +00:00
await server.set('a',2)
2020-08-20 16:31:17 +00:00
print(await server.get('a'))
await asyncio.sleep(5)
2020-08-20 15:48:08 +00:00
await server.set('a',str([2,3,4,5]))
2020-08-20 16:31:17 +00:00
print(await server.get('a'))
await asyncio.sleep(5)
2020-08-20 15:48:08 +00:00
val = await server.get('a')
print(f'VAL = {val}')
return val
asyncio.run(run())
2020-08-19 13:01:37 +00:00
def test_basic():
import asyncio
from kademlia.network import Server
2020-08-19 12:06:44 +00:00
2020-08-19 12:11:48 +00:00
#api = Api()
2020-08-19 12:06:44 +00:00
# not working!
2020-08-19 12:11:48 +00:00
#api.set_json('my key',{'a':'value'})
2020-08-19 12:06:44 +00:00
2020-08-19 13:01:37 +00:00
async def run():
# Create a node and start listening on port 5678
node = Server()
await node.listen(5678)
# Bootstrap the node by connecting to other known nodes, in this case
# replace 123.123.123.123 with the IP of another node and optionally
# give as many ip/port combos as you can for other nodes.
await node.bootstrap(NODES_PRIME)
# set a value for the key "my-key" on the network
await node.set("my-key", "my awesome value")
2020-08-20 15:48:08 +00:00
await node.set("my-key", "my awesome value2")
await node.set("my-key", "my awesome value3")
2020-08-19 13:01:37 +00:00
2020-08-20 17:10:05 +00:00
2020-08-19 13:01:37 +00:00
# get the value associated with "my-key" from the network
result = await node.get("my-key")
print(result)
return result
res = asyncio.run(run())
print('res = ',res)
# res = asyncio.run(node.set(key,value))
# print(res)
def test_provided_eg():
import asyncio
from kademlia.network import Server
async def run():
# Create a node and start listening on port 5678
node = Server()
await node.listen(5678)
# Bootstrap the node by connecting to other known nodes, in this case
# replace 123.123.123.123 with the IP of another node and optionally
# give as many ip/port combos as you can for other nodes.
await node.bootstrap(NODES_PRIME)
# set a value for the key "my-key" on the network
await node.set("my-key", "my awesome value")
# get the value associated with "my-key" from the network
result = await node.get("my-key")
print(result)
asyncio.run(run())
2020-08-19 12:06:44 +00:00
if __name__=='__main__':
2020-08-19 13:01:37 +00:00
test_api()