2
0
mirror of https://github.com/ComradCollective/Comrad synced 2024-11-05 21:20:51 +00:00

moving old api code out for now

This commit is contained in:
quadrismegistus 2020-09-14 08:58:26 +01:00
parent b12dca60ca
commit 63f92b18f0
10 changed files with 143 additions and 1414 deletions

View File

@ -1,513 +0,0 @@
# ### Constants
from komrade import *
LAST_N_IN_INBOX = 10
### Imports
import os,time,sys,logging
from pathlib import Path
import asyncio,time,sys
from base64 import b64encode,b64decode
sys.path.append(os.path.dirname(__file__))
import logging
import asyncio
import shelve
from collections import OrderedDict
import pickle,os
from threading import Thread
from pathlib import Path
# local imports
from komrade import *
CACHE_DIR = os.path.join(os.path.expanduser('~'),'.komrade','.cache')
if not os.path.exists(CACHE_DIR): os.makedirs(CACHE_DIR)
MEMCACHE_FNFN=os.path.join(CACHE_DIR,'.memory')
### Logging
def logger():
import logging
handler = logging.StreamHandler()
formatter = logging.Formatter('[%(asctime)s]\n%(message)s\n')
handler.setFormatter(formatter)
logger = logging.getLogger('komrade')
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
return logger
LOG = None
def log(*x):
global LOG
if not LOG: LOG=logger().debug
tolog=' '.join(str(_) for _ in x)
LOG(tolog)
## 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
def get_random_id():
import uuid
return uuid.uuid4().hex
def get_random_binary_id():
import base64
idstr = get_random_id()
return base64.b64encode(idstr.encode())
### Headless API
def boot_lonely_selfless_node(port=8467):
async def go():
api = Api(log=log, port=port)
await api.connect_forever()
asyncio.run(go())
class NetworkStillConnectingError(OSError): pass
async def _getdb(self=None,port=PORT_LISTEN):
from kademlia.network import Server
if self:
self.log('starting server on port %s..' % port)
import os
if self: self.log(os.getcwd())
node = Server(log=self.log if self else None) #fn='../p2p/data.db',log=(self.log if self else print)))
try:
if self: self.log('listening on port %s...' % format(port))
await node.listen(port)
except OSError:
raise NetworkStillConnectingError('Still connecting...')
#await asyncio.sleep(3)
if self: self.log('bootstrapping server..')
await node.bootstrap(NODES_PRIME)
if self: node.log = self.log
self.log('NODE:',node)
# if self and self.app:
# self.app.close_dialog()
return node
def logg(*x):
print(*x)
class Api(object):
def __init__(self,log=None,port=PORT_LISTEN):
self.log = log if log is not None else logg
self.port=port
# load file-based keys
self.load_keys()
async def connect_forever(self,save_every=60):
try:
i = 0
self._node = await self.connect()
while True:
if not i%90: self.log(f'Node status (tick {i}): {self._node}')
if i and not i%save_every: await self.flush()
i += 1
await asyncio.sleep(NODE_SLEEP_FOR)
# asyncio.sleep(0)
except (asyncio.CancelledError,KeyboardInterrupt) as e:
self.log('P2P node cancelled', e)
await self.flush()
finally:
# when canceled, print that it finished
self.log('P2P node shutting down')
pass
@property
async def node(self):
if not hasattr(self,'_node'):
await self.connect()
self._node.log=self.log
return self._node
async def connect(self):
port=self.port
# if self.app: self.app.open_dialog('hello?')
self.log('connecting on port %s...' % port)
node = await _getdb(self,port)
self.log(f'connect() has node {node}')
self._node = node
return node
def get_tor_python_session(self):
# from torpy.http.requests import TorRequests
# with TorRequests() as tor_requests:
# with tor_requests.get_session() as s:
# # return s
# from torpy.http.requests import tor_requests_session
# with tor_requests_session() as s: # returns requests.Session() object
# return s
pass
def get_tor_proxy_session(self):
session = requests.session()
# Tor uses the 9050 port as the default socks port
session.proxies = {'http': 'socks5://127.0.0.1:9050',
'https': 'socks5://127.0.0.1:9050'}
return session
def get_async_tor_proxy_session(self):
from requests_futures.sessions import FuturesSession
session = FuturesSession()
# Tor uses the 9050 port as the default socks port
session.proxies = {'http': 'socks5://127.0.0.1:9050',
'https': 'socks5://127.0.0.1:9050'}
return session
def tor_request(self,url,method='get',data=None):
stopfixthis
with self.get_tor_proxy_session() as s:
if method=='get':
return s.get(url)
elif method=='post':
self.log('data',data)
return s.post(url,data=data)
def request(self,Q,**kwargs):
self.log('request() Q:',Q)
res = self.tor_request(Q,**kwargs)
self.log('reqeust() <-',res)
return res
#@property
def load_keys(self):
# get key names
pub_key_names = [x.split('.')[1] for x in os.listdir(KEY_PATH_PUB) if x.count('.')==2 and x.endswith('.loc')]
priv_key_names = [x.split('.')[1] for x in os.listdir(KEY_PATH_PRIV) if x.count('.')==2 and x.endswith('.key')]
key_names = set(pub_key_names)|set(priv_key_names)
self.log('get_keys() found public key names:',pub_key_names)
self.log('get_keys() found private key names:',priv_key_names)
# load and find all local
self._keys = {}
for key_name in key_names:
self.log('key_name =',key_name)
self._keys[key_name] = Komrade(key_name,api=self,create_if_missing=False)
# break into types
self.accounts = [self._keys[name] for name in priv_key_names]
self.contacts = [self._keys[name] for name in pub_key_names]
self.log('get_keys() loaded accounts:',self.accounts)
self.log('get_keys() loaded contacts:',self.contacts)
@property
def keys(self):
if not hasattr(self,'_keys'): self.load_keys()
return self._keys
#async
def personate(self,persona_name,create_if_missing=True):
komrade = Komrade(persona_name,api=self,create_if_missing=create_if_missing)
res = persona.boot()
self.log('personate() res =',res)
return persona
# komrade = self.keys[persona_name] if persona_name in self.keys else None
# if komrade is None and create_if_missing:
# self.keys[persona_name] = komrade = Komrade(persona_name, api=self, create_if_missing=create_if_missing)
# res = await persona.boot()
# self.log('BOOT RESULT:',res)
# return persona
async def upload(self,filename,file_id=None, uri='/file/',uri_part='/part/'):
import sys
if not file_id: file_id = get_random_id()
part_ids = []
part_keys = []
parts=[]
PARTS=[]
buffer_size=100
for part in bytes_from_file(filename,chunksize=1024*2):
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)
# self.log('part!:',sys.getsizeof(part))
#self.set(part_key,part)
if len(parts)>=buffer_size:
# self.log('setting...')
await self.set(part_keys,parts)
part_keys=[]
PARTS+=parts
parts=[]
# set all parts
#self.set(part_keys,PARTS)
# self.log('# parts:',len(PARTS))
if parts and part_keys:
await self.set(part_keys, parts)
# how many parts?
# self.log('# pieces!',len(part_ids))
file_store = {'ext':os.path.splitext(filename)[-1][1:], 'parts':part_ids}
# self.log('FILE STORE??',file_store)
await self.set_json(uri+file_id,file_store)
# file_store['data'].seek(0)
file_store['id']=file_id
return file_store
async def download(self,file_id):
self.log('file_id =',file_id)
file_store = await self.get_json_val('/file/'+file_id)
self.log('file_store =',file_store)
if file_store is None: return
self.log('file_store!?',file_store)
keys = ['/part/'+x for x in file_store['parts']]
#time,pieces,pub,sign = await self.get_json_val(keys)
pieces = await self.get_json_val(keys)
self.log('pieces = ',pieces)
file_store['parts_data']=pieces
return file_store
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...')
async def get_posts(self,uri='/inbox/world'):
# get IDs
post_ids = await self.get_post_ids(uri)
# get posts
posts = [self.get_post(post_id) for post_id in post_ids]
return await asyncio.gather(*posts)
async def read_inbox(self,uri_inbox=None):
if uri_inbox is None: uri_inbox = P2P_PREFIX_INBOX+self.name.encode()
node = await self.node
inbox_ids = await node.get(uri_inbox)
if inbox_ids is not None:
inbox_ids = inbox_ids.split(BSEP)
self.log('found inbox IDs:',inbox_ids)
msgs_toread = [self.read_msg(msg_id) for msg_id in inbox_ids]
msgs = await asyncio.gather(*msgs_toread)
self.log('read_inbox() msgs = ',msgs)
return msgs
return []
async def read_outbox(self,uri_outbox=None):
if uri_outbox is None: uri_outbox = P2P_PREFIX_OUTBOX+self.name.encode()
return await self.read_inbox(uri_outbox)
async def read_msg(self,msg_id):
self.log(f'Persona.read_msg({msg_id}) ?')
uri_msg=P2P_PREFIX_POST+msg_id
node = await self.node
komrade = await self.komrade
res = await node.get(uri_msg)
self.log('res = ',res)
if res is not None:
double_encrypted_payload_b64 = res
single_encrypted_payload = self.decrypt(double_encrypted_payload_b64, komrade.pubkey_b64)
self.log('GOT ENRYPTED PAYLOAD:',single_encrypted_payload)
signed_encrypted_payload_b64,from_pubkey_b64,name_b64,time_b64 = single_encrypted_payload.split(BSEP)
self.log('signed_encrypted_payload =',signed_encrypted_payload_b64)
self.log('from_pubkey_b64 =',from_pubkey_b64)
self.log('time_b64 =',time_b64)
from_name = b64decode(name_b64).decode()
self.log('from_name =',from_name)
timestamp = b64decode(time_b64).decode()
tmpP = Komrade(from_name)
await tmpP.boot()
from_pubkey_b64_accto_name = tmpP.pubkey_b64
assert from_pubkey_b64==from_pubkey_b64_accto_name
encrypted_payload_b64 = self.verify(signed_encrypted_payload_b64, from_pubkey_b64)
self.log('encrypted_payload_b64 =',encrypted_payload_b64)
payload = self.decrypt(encrypted_payload_b64, from_pubkey_b64)
self.log('payload =',payload)
return {
'success':True,
'content':payload,
'from_name':from_name,
'from_pubkey_b64':from_pubkey_b64,
'timestamp':timestamp
}
return {'error':'Unknown'}
async def refresh_inboxes(self):
uris_to_get=[]
for komrade in self.accounts:
inbox = await persona.load_inbox(decrypt_msg_uri=True, last=LAST_N_IN_INBOX)
for decr_msg_uri in inbox:
uris_to_get.append(self.get_msg(decr_msg_uri))
# uris_to_get+=inbox
res = await asyncio.gather(*uris_to_get)
for decr_msg_uri,encr_msg in res:
self.memcache[decr_msg_uri]=encr_msg
self.memcache_save()
@property
def memcache(self):
if not hasattr(self,'_memcache'):
self._memcache = OrderedDict()
if os.path.exists(MEMCACHE_FNFN):
import pickle
try:
self._memcache = pickle.load(open(MEMCACHE_FNFN,'rb'))
except EOFError:
pass
return self._memcache
def memcache_save(self):
import pickle
with open(MEMCACHE_FNFN,'wb') as of:
pickle.dump(self.memcache, of)
self.log('>> saved:',MEMCACHE_FNFN)
async def get_msg(self,decr_msg_uri):
self.log('get_msg()',decr_msg_uri)
rval=self.memcache.get(decr_msg_uri)
self.log('got <--',rval)
if rval is not None:
self.log('in memcache')
encr_msg = rval
else:
self.log('>> downloading',decr_msg_uri,'...')
node = await self.node
encr_msg = await node.get(decr_msg_uri)
self.log('downloaded:',encr_msg)
return (decr_msg_uri,encr_msg)
#self.memcache.
async def see(self,decr_msg_id):
res=await self.get(decr_msg_id)
self.log('see() saw',res)
return decr_msg_id
async def test1():
api = Api()
marx=await api.personate('marx')
elon=await api.personate('elon')
res = await marx.send(b'secret',to=elon)
print(marx,elon,res)
async def test():
api = Api()
# message?
marx=await api.personate('marx')
elon=await api.personate('elon')
res = await marx.send(b'secret',to=elon)
res = await elon.send(b'secret back',to=marx)
# print(marx,elon,res)
# get overall inbox
meta_inbox = await api.refresh_inboxes()
api.log('meta_inbox',meta_inbox)
keys = api.memcache.keys()
api.log('ALL KEYS =',keys)
for key in keys:
val = api.memcache.get(key)
api.log(key,'-->',val)
# stop
#async
async def test_keyserver():
api = Api()
marx = api.personate('marx')
elon = api.personate('elon')
zuck = api.personate('zuck')
print('marx',marx.pubkey_b64)
print('elon',elon.pubkey_b64)
print('zuck',zuck.pubkey_b64)
#marx = await api.personate(marx)
#res = await api.get_externally_signed_pubkey('marx')
#res = await api.get_externally_signed_pubkey('marx')
#return res
await elon.send(b'oh no',to=marx)
if __name__=='__main__':
asyncio.run(test_keyserver())

View File

@ -1,81 +0,0 @@
# mine imports
import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..')))
from komrade.backend.caller import Caller
from komrade import KomradeException,Logger
# other imports
import asyncio,os,time,sys,logging,getpass
from pythemis.skeygen import KEY_PAIR_TYPE, GenerateKeyPair
from pythemis.smessage import SMessage, ssign, sverify
from pythemis.exception import ThemisError
from pythemis.scell import SCellSeal
from base64 import b64decode,b64encode
from pathlib import Path
class Model(Logger): pass
class UserAlreadyExists(KomradeException): pass
class Komrade(Model):
def __init__(self, name, is_group=False):
self.name = name
self.is_group=is_group
@property
def op(self):
return Caller(self.name)
###
# MAJOR OPERATIONS
###
def register(self,passphrase = DEBUG_DEFAULT_PASSPHRASE):
"""
Register this new persona.
Protect keys according to a passphrase.
If group, only admin key pass-protected;
if individual, all keys pass-protected.
"""
# Does user already exist?
if self.op.exists(): raise UserAlreadyExists('User already exists')
# Get passphrase
if not passphrase: passphrase = getpass.getpass('Enter password for new account: ')
# Create
if self.is_group:
self.op.create_keys(adminkey_pass=passphrase)
else:
self.op.create_keys(privkey_pass=passphrase,adminkey_pass=passphrase)
def login(self,passphrase = DEBUG_DEFAULT_PASSPHRASE):
# Get passphrase
if not passphrase: passphrase = getpass.getpass('Enter login password: ')
# Get my decryption keys
if self.is_group:
keychain_decr = self.op.keychain_decr(adminkey_pass=passphrase)
else:
keychain_decr = self.op.keychain_decr(privkey_pass=passphrase,adminkey_pass=passphrase)
print(keychain_decr)
if __name__ == '__main__':
import random
idnum = random.choice(list(range(1000)))
komrade = Komrade('Op'+str(idnum))
print('\n\n\nREGISTERING\n\n\n')
persona.register(passphrase='bb')
print('\n\n\nLOGGING IN\n\n\n')
persona.login(passphrase='bb')

View File

@ -1,739 +0,0 @@
import os
import asyncio
from pythemis.skeygen import KEY_PAIR_TYPE, GenerateKeyPair
from pythemis.smessage import SMessage, ssign, sverify
from pythemis.exception import ThemisError
from pythemis.scell import SCellSeal
from base64 import b64decode,b64encode
# from kademlia.network import Server
import os,time,sys,logging
from pathlib import Path
import requests
sys.path.append('../p2p')
BSEP=b'||||||||||'
BSEP2=b'@@@@@@@@@@'
BSEP3=b'##########'
NODE_SLEEP_FOR=1
P2P_PREFIX=b'/persona/'
P2P_PREFIX_POST=b'/msg/'
P2P_PREFIX_INBOX=b'/inbox/'
P2P_PREFIX_OUTBOX=b'/outbox/'
WORLD_PUB_KEY = b'VUVDMgAAAC1z53KeApQY4RICK5k0nXnnS+K17veIFMPlFKo7mqnRhTZDhAmG'
WORLD_PRIV_KEY = b'UkVDMgAAAC26HXeGACxZUoKYKlZ7sDmVoLwffNj3CrdqoPrE94+2ysfhufmP'
KOMRADE_PUB_KEY = b'VUVDMgAAAC09uo+wAgu/V9xyvMkMDbOQEk1ssOrFADaiyTzfwVjE6o8FHoil'
KOMRADE_PRIV_KEY = b'UkVDMgAAAC33fFiaAIpmQewjkYndzMcMkj1mLy/lE4RXJQzIlUN94tyC5g29'
DEBUG = True
UPLOAD_DIR = 'uploads/'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
PORT_LISTEN = 5639
NODE_SLEEP_FOR=1
NODES_PRIME = [("128.232.229.63",8467)]
KEYSERVER_ADDR = 'komrade.app' #'128.232.229.63'
KEYSERVER_PORT = 5566
KEY_PATH = os.path.join(os.path.expanduser('~'),'.komrade')
KEY_PATH_PUB = os.path.join(KEY_PATH,'.locs')
KEY_PATH_PRIV = os.path.join(KEY_PATH,'.keys')
for x in [KEY_PATH,KEY_PATH_PUB,KEY_PATH_PRIV]:
if not os.path.exists(x): os.makedirs(x)
WORLD_PRIV_KEY_FN = os.path.join(KEY_PATH_PRIV,'.world.key')
WORLD_PUB_KEY_FN = os.path.join(KEY_PATH_PUB,'.world.loc')
KOMRADE_PRIV_KEY_FN = os.path.join(KEY_PATH_PRIV,'.komrade.key')
KOMRADE_PUB_KEY_FN = os.path.join(KEY_PATH_PUB,'.komrade.loc')
def check_world_keys():
if not os.path.exists(WORLD_PRIV_KEY_FN):
with open(WORLD_PRIV_KEY_FN,'wb') as of:
of.write(WORLD_PRIV_KEY)
if not os.path.exists(WORLD_PUB_KEY_FN):
with open(WORLD_PUB_KEY_FN,'wb') as of:
of.write(WORLD_PUB_KEY)
if not os.path.exists(KOMRADE_PRIV_KEY_FN):
with open(KOMRADE_PRIV_KEY_FN,'wb') as of:
of.write(KOMRADE_PRIV_KEY)
if not os.path.exists(KOMRADE_PUB_KEY_FN):
with open(KOMRADE_PUB_KEY_FN,'wb') as of:
of.write(KOMRADE_PUB_KEY)
# check_world_keys()
## CONNECTING
## utils
def get_random_id():
import uuid
return uuid.uuid4().hex
def get_random_binary_id():
import base64
idstr = get_random_id()
return base64.b64encode(idstr.encode())
def logger():
import logging
handler = logging.StreamHandler()
formatter = logging.Formatter('[%(asctime)s]\n%(message)s\n')
handler.setFormatter(formatter)
logger = logging.getLogger(__file__)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
return logger
LOG = None
def log(*x):
global LOG
if not LOG: LOG=logger().debug
tolog=' '.join(str(_) for _ in x)
LOG(tolog)
class NetworkStillConnectingError(OSError): pass
class Komrade(object):
def __init__(self,name,api=None,node=None,create_if_missing=True):
self.name=name
self.log=log
self.privkey=None
self.pubkey=None
self.api=api
self.can_receive = False
self.can_send = False
# self.can_login = False
self.external_keys_loaded = False
self.pubkey_enc = None
self.pubkey_decr = None
# self._node=node
self.create_if_missing=create_if_missing
# self.log(f'>> Persona.__init__(name={name},create_if_missing={create_if_missing})')
# load at least any local keys (non-async)
self.find_keys_local()
# self.login_or_register()
def __repr__(self):
#pkeystr = '+loc' if self.has_public_key() else ''
#privkeystr = ' +key' if self.has_private_key() else ''
# ptypestr='acccount' if self.has_private_key() else 'contact'
ptypestr='loc' if not self.has_private_key() else 'keyloc'
return f'{self.name} ({ptypestr})'
def get_keyserver_pubkey(self):
Q=f'http://{KEYSERVER_ADDR}:{KEYSERVER_PORT}/pub'
r = self.api.request(Q)
return r.content
# self.log('r =',r,b64encode(r.content))
# pubkey_b64 = b64encode(r.content)
# return pubkey_b64
def get_externally_signed_pubkey(self):
Q=f'http://{KEYSERVER_ADDR}:{KEYSERVER_PORT}/get/{self.name}'
self.log('Q:',Q)
r = self.api.request(Q)
package_b64 = r.content
package = b64decode(package_b64)
self.log('package <--',package)
if not package: return (b'',b'',b'')
return package.split(BSEP)
# pubkey_b64, signed_pubkey_b64, server_signed_pubkey_b64 = package.split(BSEP)
# signed_pubkey = b64encode(r.content)
# return (b64encode(pubkey), b64encode(signed_pubkey))
def set_externally_signed_pubkey(self):
import requests
Q=f'http://{KEYSERVER_ADDR}:{KEYSERVER_PORT}/add/{self.name}' #/{name}/{key}
package = self.pubkey_b64 + BSEP + self.signed_pubkey_b64
self.log('set_externally_signed_pubkey package -->',package)
r = requests.post(Q, data=package) #{'name':self.name,'key':self.pubkey_b64})
return r
def has_private_key(self):
return self.privkey is not None
def has_public_key(self):
return self.pubkey is not None
@property
async def node(self):
node = await self.api.node
return node
def load_keyserver_pubkey(self):
self.keyserver_pubkey_b64 = self.get_keyserver_pubkey()
self.keyserver_pubkey = b64decode(self.keyserver_pubkey_b64)
self.log('keyserver_pubkey =',self.keyserver_pubkey)
return self.keyserver_pubkey
def load_external_keys(self):
if self.external_keys_loaded: return
self.pubkey_ext_b64, self.signed_pubkey_ext_b64, self.server_signed_pubkey_ext_b64 = self.get_externally_signed_pubkey()
self.log('pubkey_ext_b64 =',self.pubkey_ext_b64)
self.log('signed_pubkey_ext_b64 =',self.signed_pubkey_ext_b64)
self.log('server_signed_pubkey_ext_b64 =',self.server_signed_pubkey_ext_b64)
self.external_keys_loaded = True
def keyserver_name_exists(self):
user_missing = (self.pubkey_ext_b64 is b'' or self.signed_pubkey_ext_b64 is b'' or self.server_signed_pubkey_ext_b64 is b'')
return not user_missing
def meet(self,save_loc=True):
pubkey_ext = b64decode(self.pubkey_keyserver_verified)
self.log('pubkey_ext',pubkey_ext)
self.pubkey=pubkey_ext
self.log('setting self.pubkey to external value:',self.pubkey)
self.log('self.pubkey_64',self.pubkey_b64)
self.log('keyserver_verified',self.pubkey_keyserver_verified)
with open(self.key_path_pub,'wb') as of:
of.write(self.pubkey_keyserver_verified)
return {'success':'Met person as acquaintance'}
def register(self):
# register
if self.create_if_missing:
self.gen_keys()
res = self.set_externally_signed_pubkey()
self.log('set_externally_signed_pubkey res =',res)
if res is None:
return {'error':'Could not set externally signed pubkey'}
else:
return {'success':'Created new pubkey'}
else:
return {'error':'No public key externally, but create_if_missing==False'}
# login, meet, or register
def boot(self):
# keyserver active?
keyserver_pubkey = self.keyserver_pubkey = self.load_keyserver_pubkey()
if keyserver_pubkey is None:
return {'error':'Cannot conntact keyserver'}
# load external keys
self.load_external_keys()
# user exists...
if self.keyserver_name_exists():
# if I claim to be this person
if self.privkey and self.pubkey_decr:
attempt = self.login()
self.log('login attempt ->',attempt)
return attempt
# otherwise just meet them
attempt = self.meet()
self.log('meet attempt ->',attempt)
return attempt
# user does not exist
attempt = self.register()
self.log('register attempt -->',attempt)
return attempt
@property
def key_path_pub(self):
return os.path.join(KEY_PATH_PUB,'.'+self.name+'.loc')
@property
def key_path_pub_enc(self):
return os.path.join(KEY_PATH_PUB,'.'+self.name+'.loc.box')
@property
def key_path_priv(self):
return os.path.join(KEY_PATH_PRIV,'.'+self.name+'.key')
@property
def name_b64(self):
return b64encode(self.name.encode())
@property
def privkey_b64(self):
return b64encode(self.privkey)
@property
def pubkey_b64(self):
return b64encode(self.pubkey) if self.pubkey else b''
@property
def signed_pubkey_b64(self):
return self.sign(self.pubkey_b64)
# return self.encrypt(self.pubkey_b64, self.pubkey_b64)
## genearating keys
# def gen_keys1(self):
# self.log('gen_keys()')
# keypair = GenerateKeyPair(KEY_PAIR_TYPE.EC)
# self.privkey = keypair.export_private_key()
# self.pubkey = keypair.export_public_key()
# self.log(f'priv_key saved to {self.key_path_priv}')
# with open(self.key_path_priv, "wb") as private_key_file:
# private_key_file.write(self.privkey_b64)
# with open(self.key_path_pub, "wb") as public_key_file:
# # save SIGNED public key
# public_key_file.write(self.pubkey_b64)
# with open(self.key_path_pub_enc,'wb') as signed_public_key_file:
# # self.log('encrypted_pubkey_b64 -->',self.encrypted_pubkey_b64)
# pubkey_b64 = b64encode(self.pubkey)
# self.log('pubkey',self.pubkey)
# self.log('pubkey_b64',pubkey_b64)
# encrypted_pubkey_b64 = self.encrypt(pubkey_b64, pubkey_b64, KOMRADE_PRIV_KEY)
# self.log('encrypted_pubkey_b64 -->',encrypted_pubkey_b64)
# signed_public_key_file.write(encrypted_pubkey_b64)
def gen_keys(self,passphrase=DEBUG_DEFAULT_PASSPHRASE):
"""
Generate private/public key pair
Secure that with passphrase
"""
## Generate key pair
self.log('gen_keys()')
keypair = GenerateKeyPair(KEY_PAIR_TYPE.EC)
self.privkey = keypair.export_private_key()
self.pubkey = keypair.export_public_key()
## Secure with passphrase
if passphrase is None: passphrase=input('Please protect account with passphrase:\n')
cell = SCellSeal(passphrase=passphrase)
keypair_b = self.privkey + BSEP + self.pubkey
keypair_b_encr = cell.encrypt(keypair_b)
self.log(f'priv_key saved to {self.key_path_priv}')
with open(self.key_path_priv, "wb") as private_key_file:
private_key_file.write(self.privkey_b64)
with open(self.key_path_pub, "wb") as public_key_file:
# save SIGNED public key
public_key_file.write(self.pubkey_b64)
with open(self.key_path_pub_enc,'wb') as signed_public_key_file:
# self.log('encrypted_pubkey_b64 -->',self.encrypted_pubkey_b64)
pubkey_b64 = b64encode(self.pubkey)
self.log('pubkey',self.pubkey)
self.log('pubkey_b64',pubkey_b64)
encrypted_pubkey_b64 = self.encrypt(pubkey_b64, pubkey_b64, KOMRADE_PRIV_KEY)
self.log('encrypted_pubkey_b64 -->',encrypted_pubkey_b64)
signed_public_key_file.write(encrypted_pubkey_b64)
## loading keys from disk
def find_keys_local(self):
self.log(f'find_keys_local(path_pub={self.key_path_pub}, path_priv={self.key_path_priv})')
if os.path.exists(self.key_path_priv):
with open(self.key_path_priv) as priv_f:
self.privkey=b64decode(priv_f.read())
# Load from encrypted?
if os.path.exists(self.key_path_pub_enc) and self.privkey:
with open(self.key_path_pub_enc) as pub_f:
self.pubkey_enc=pub_f.read()
self.pubkey_decr=self.decrypt(self.pubkey_enc, KOMRADE_PUB_KEY)
# self.pubkey=self.pubkey_decr
self.log('loaded self.pubkey from enc',self.pubkey)
self.can_receive = True
self.can_send = True
# load from nonencrypted pubkey?
if os.path.exists(self.key_path_pub):
with open(self.key_path_pub) as pub_f:
self.pubkey=b64decode(pub_f.read())
self.log('loaded self.pubkey from UNenc',self.pubkey)
self.can_receive = True
@property
def pubkey_keyserver_verified(self):
# test if remote data agrees
if not hasattr(self,'_keyserver_verified'):
self._keyserver_verified = self.verify(self.server_signed_pubkey_ext_b64, self.keyserver_pubkey_b64)
return self._keyserver_verified
def login(self):
# test if local data present
if not self.pubkey or not self.pubkey_decr:
return {'error':'Public keys not present'}
# test if local data agrees
self.log('self.pubkey',self.pubkey_b64)
self.log('self.pubkey_decr',self.pubkey_decr)
if self.pubkey_b64 != self.pubkey_decr:
return {'error':'Public keys do not match'}
# test if remote data agrees
keyserver_verified = self.pubkey_keyserver_verified
if keyserver_verified is None:
return {'error':'Keyserver verification failed'}
# test if pubkey match
enc_match = self.pubkey_decr == keyserver_verified
if enc_match:
return {'success':'Keys matched'}
return {'error':'Keys did not match'}
## E/D/S/V
def encrypt(self,msg_b64,for_pubkey_b64, privkey_b64=None):
self.log('encrypt()',msg_b64,for_pubkey_b64,privkey_b64)
privkey = b64decode(privkey_b64) if privkey_b64 else self.privkey
# handle verification failure
for_pubkey = b64decode(for_pubkey_b64)
encrypted_msg = SMessage(privkey, for_pubkey).wrap(msg_b64)
return b64encode(encrypted_msg)
def decrypt(self,encrypted_msg_b64,from_pubkey_b64, privkey_b64=None):
privkey = b64decode(privkey_b64) if privkey_b64 else self.privkey
# handle verification failure
from_pubkey = b64decode(from_pubkey_b64)
encrypted_msg = b64decode(encrypted_msg_b64)
decrypted_msg = SMessage(privkey, from_pubkey).unwrap(encrypted_msg)
return decrypted_msg
def sign(self,msg_b64, privkey=None):
if not privkey: privkey=self.privkey
signed_msg = b64encode(ssign(privkey, msg_b64))
return signed_msg
def verify(self,signed_msg_b64,pubkey_b64=None):
if pubkey_b64 is None: pubkey_b64=self.pubkey_b64
self.log('verify() signed_msg_b64 =',signed_msg_b64)
self.log('verify() pubkey_b64 =',pubkey_b64)
signed_msg = b64decode(signed_msg_b64)
public_key = b64decode(pubkey_b64)
self.log('verify() signed_msg =',signed_msg)
self.log('verify() public_key =',public_key)
try:
verified_msg = sverify(public_key, signed_msg)
return verified_msg
except ThemisError as e:
print('!!',e)
return None
@property
def uri_inbox(self):
return P2P_PREFIX_INBOX+self.name.encode()
@property
def uri_outbox(self):
return P2P_PREFIX_OUTBOX+self.name.encode()
@property
def app_pubkey_b64(self):
return KOMRADE_PUB_KEY
## POSTING/SENDING MSGS
async def post(self,encrypted_payload_b64,to_person):
# double wrap
double_encrypted_payload = self.encrypt(encrypted_payload_b64, to_person.pubkey_b64, KOMRADE_PRIV_KEY)
self.log('double_encrypted_payload =',double_encrypted_payload)
post_id = get_random_binary_id() #get_random_id().encode()
node = await self.node
uri_post = P2P_PREFIX_POST + post_id
res = await node.set(uri_post, double_encrypted_payload)
self.log('result of post() =',res)
return uri_post
async def send(self,msg_b,to,from_person=None):
"""
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
"""
if type(msg_b)==str: msg_b=msg_b.encode()
msg_b64=b64encode(msg_b)
# encrypt and sign
to_person = to
if from_person is None: from_person = self
encrypted_payload = from_person.encrypt(msg_b64, to_person.pubkey_b64)
signed_encrypted_payload = from_person.sign(encrypted_payload)
# package
time_b64 = b64encode(str(time.time()).encode())
WDV_b64 = b64encode(BSEP.join([
signed_encrypted_payload,
from_person.pubkey_b64,
from_person.name_b64,
time_b64]))
self.log('WDV_b64 =',WDV_b64)
# post
post_id = await self.post(WDV_b64, to_person)
self.log('post_id <-',post_id)
# add to inbox
res = await to_person.add_to_inbox(post_id)
self.log('add_to_inbox <-',res)
# add to outbox?
# pass
async def load_inbox(self,decrypt_msg_uri=False,last=None):
node = await self.node
encrypted_inbox_idstr_b64 = await node.get(self.uri_inbox)
self.log('encrypted_inbox_idstr_b64 =',encrypted_inbox_idstr_b64)
if encrypted_inbox_idstr_b64 is None: return []
# inbox_idstr = self.decrypt(encrypted_inbox_idstr_b64, self.app_pubkey_b64)
# self.log('decrypted inbox_idstr =',inbox_idstr)
# decrypt!
encrypted_inbox_idstr = b64decode(encrypted_inbox_idstr_b64)
self.log('encrypted_inbox_idstr =',encrypted_inbox_idstr)
inbox_ids = encrypted_inbox_idstr.split(BSEP) if encrypted_inbox_idstr is not None else []
self.log('inbox_ids =',inbox_ids)
if decrypt_msg_uri:
inbox_ids = [self.decrypt(enc_msg_id_b64,KOMRADE_PUB_KEY) for enc_msg_id_b64 in inbox_ids]
self.log('inbox_ids decrypted =',inbox_ids)
return inbox_ids[:last]
async def add_to_inbox(self,msg_uri,inbox_sofar=None):
# encrypt msg id so only inbox owner can resolve the pointer
self.log('unencrypted msg uri:',msg_uri)
encrypted_msg_uri = self.encrypt(msg_uri, self.pubkey_b64, KOMRADE_PRIV_KEY)
self.log('encrypted msg uri:',encrypted_msg_uri)
# get current inbox
if inbox_sofar is None: inbox_sofar=await self.load_inbox()
self.log('inbox_sofar:',inbox_sofar)
# add new value
new_inbox = inbox_sofar + [encrypted_msg_uri]
new_inbox_b = BSEP.join(new_inbox)
self.log('new_inbox_b:',new_inbox_b)
new_inbox_b64 = b64encode(new_inbox_b)
self.log('new_inbox_b64:',new_inbox_b64)
# set on net
node = await self.node
await node.set(self.uri_inbox,new_inbox_b64)
new_length = len(new_inbox)
return {'success':'Inbox length increased to %s' % new_length}
#return {'error':'Could not append data'}
async def add_to_outbox(self):
"""
Do not store on server!
"""
pass
async def read_inbox(self,uri_inbox=None):
if uri_inbox is None: uri_inbox = P2P_PREFIX_INBOX+self.name.encode()
node = await self.node
inbox_ids = await node.get(uri_inbox)
if inbox_ids is not None:
inbox_ids = inbox_ids.split(BSEP)
self.log('found inbox IDs:',inbox_ids)
msgs_toread = [self.read_msg(msg_id) for msg_id in inbox_ids]
msgs = await asyncio.gather(*msgs_toread)
self.log('read_inbox() msgs = ',msgs)
return msgs
return []
async def read_outbox(self,uri_outbox=None):
if uri_outbox is None: uri_outbox = P2P_PREFIX_OUTBOX+self.name.encode()
return await self.read_inbox(uri_outbox)
async def read_msg(self,msg_id):
self.log(f'Persona.read_msg({msg_id}) ?')
uri_msg=P2P_PREFIX_POST+msg_id
node = await self.node
res = await node.get(uri_msg)
self.log('res = ',res)
if res is not None:
double_encrypted_payload_b64 = res
single_encrypted_payload = self.decrypt(double_encrypted_payload_b64, KOMRADE_PUB_KEY)
self.log('GOT ENRYPTED PAYLOAD:',single_encrypted_payload)
signed_encrypted_payload_b64,from_pubkey_b64,name_b64,time_b64 = single_encrypted_payload.split(BSEP)
self.log('signed_encrypted_payload =',signed_encrypted_payload_b64)
self.log('from_pubkey_b64 =',from_pubkey_b64)
self.log('time_b64 =',time_b64)
from_name = b64decode(name_b64).decode()
self.log('from_name =',from_name)
timestamp = b64decode(time_b64).decode()
tmpP = Komrade(from_name)
await tmpP.boot()
from_pubkey_b64_accto_name = tmpP.pubkey_b64
assert from_pubkey_b64==from_pubkey_b64_accto_name
encrypted_payload_b64 = self.verify(signed_encrypted_payload_b64, from_pubkey_b64)
self.log('encrypted_payload_b64 =',encrypted_payload_b64)
payload = self.decrypt(encrypted_payload_b64, from_pubkey_b64)
self.log('payload =',payload)
return {
'success':True,
'content':payload,
'from_name':from_name,
'from_pubkey_b64':from_pubkey_b64,
'timestamp':timestamp
}
return {'error':'Unknown'}
def run_multiple_tasks(tasks):
async def _go(tasks):
res = await asyncio.gather(*tasks, return_exceptions=True)
return res
return asyncio.get_event_loop().run_until_complete(_go(tasks))
async def main():
# start node
from kademlia.network import Server
#from p2p_api import
PORT_LISTEN = 5969
# NODES_PRIME = [("128.232.229.63",8467), ("68.66.241.111",8467)]
NODES_PRIME = [("128.232.229.63",8467)]
node = Server(log=log)
await node.listen(PORT_LISTEN)
await node.bootstrap(NODES_PRIME)
marx = Komrade('marx',node=node)
elon = Komrade('elon2',node=node)
world = Komrade('world',node=node)
await world.boot()
await marx.boot()
await elon.boot()
# await marx.send(b'Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! Secret message 2! ',to=elon)
# await elon.read_inbox()
await marx.send(b'A specter is haunting the internet',to=world)
await elon.send(b'My rockets explode and so will your mind',to=world)
await elon.send(b'My rockets explode and so will your mind',to=world)
await world.read_inbox()
return True
if __name__=='__main__':
asyncio.run(main())

View File

@ -1 +0,0 @@
python -c "import api; api.boot_lonely_selfless_node()"

View File

@ -12,7 +12,7 @@ from komrade.backend.keymaker import *
class KomradeX(Caller):
def __init__(self, name=None, passphrase=DEBUG_DEFAULT_PASSPHRASE):
def __init__(self, name=None, pubkey=None, passphrase=DEBUG_DEFAULT_PASSPHRASE):
super().__init__(name=name,passphrase=passphrase)
# self.log(f'booted komrade with {name} and {passphrase} and\n\n{dict_format(self.keychain())}')
# if SHOW_STATUS:
@ -27,6 +27,8 @@ class KomradeX(Caller):
# yes? -- login
keys = self.keychain()
self.log(f'booting {self}!',dict_format(keys))
if keys.get('pubkey') and keys.get('privkey'):
# self.log('already booted! @'+self.name)
return True
@ -203,29 +205,30 @@ class KomradeX(Caller):
)
def login(self,passphrase=None):
# check hardware
if not self.pubkey:
self.log('''Login impossible. I do not have this komrade's public key, much less private one.''')
return
if not self.privkey_encr:
self.log('''Login impossible. I do not have this komrade's private key on this hardware.''')
return
# what keys do I have?
keys = self.keychain()
# self.log('here are my keys:',dict_format(keys))
# check password
while not passphrase:
from getpass import getpass
passphrase = getpass('@Keymaker: Enter password for {self} in order to decrypt the encrypted private key:\n\n')
# assemble privkey?
privkey = self.keychain(passphrase=passphrase).get('privkey')
if not privkey:
self.log('''Login impossible. I do not have this komrade's private key on this hardware.''')
return
# check hardware
if not 'pubkey' in keys:
emsg='''Login impossible. I do not have this komrade's public key, much less private one.'''
# self.log()
return {'success':False, 'status':emsg}
if not 'privkey_encr' in keys:
emsg='''Login impossible. I do not have this komrade's private key on this hardware.'''
self.log(emsg)
return {'success':False, 'status':emsg}
if not 'privkey' in keys:
emsg='''Login failed. Private key did not unlock from passphrase.'''
return {'success':False, 'status': emsg}
# compose message
msg = {
'name':self.name,
'pubkey':self.pubkey.data,
'pubkey':keys['pubkey'].data,
'secret_login':self.secret_login
}
@ -270,18 +273,41 @@ class KomradeX(Caller):
def send_msg_to(self,msg,to_whom):
to_whom = self.find(to_whom)
self.log(f'found {to_whom}')
def msg(self,someone,something):
# find or boot
someone = Komrade(someone)
self.log(f'found {someone}')
# can we?
if not someone.pubkey:
self.log(f'''Don't know the public key of {someone}!''')
msg_obj = self.compose_msg_to(
msg,
to_whom
something,
someone
)
self.log('composed msg:',msg_obj)
msg_obj.encrypt()
self.log('going to send msg_d?',msg_obj.msg_d)
return self.ring_ring(msg_obj.msg_d)
# encrypting
msg_obj.encrypt()
# attaching
direct_msg_data = msg_obj.msg
self.log('going to send only this to op:',direct_msg_data)
# enclosing
msg_to_op = {
'deliver_from':self.pubkey.data_b64,
'deliver_to':someone.pubkey.data_b64,
'deliver_msg':direct_msg_data,
}
self.log('going to send msg to op?',msg_to_op)
return self.ring_ring(
msg_to_op,
route='deliver_msg'
)
@ -304,17 +330,20 @@ def test_msg():
z.send_msg_to('you ssssssuck')
def test_loading():
# z1 = Komrade('zuck')
# print(z1.keychain())
z2 = Komrade(b'VUVDMgAAAC08BCMVA+0dMJXc66/W7hty669+3/3S61Q1yjmgJW8I0k3lqfDi')
print(z2)
print(z2.keychain())
pprint(PHONEBOOK)
return
# z1.login()
if __name__=='__main__':
test_msg()
# marx = Komrade('marx')
# elon = Komrade('elon')
# marx.register()
# # elon.register()
# # person.register()
# # print(person.pubkey)
# # elon.send_msg_to('youre dumb',marx)
# #Caller('elon').ring_ring({'_route':'say_hello','msg':'my dumb message to operator'})
# # print(marx.exists_on_server())
test_loading()

View File

@ -8,7 +8,13 @@ from komrade.backend import *
PHONEBOOK = {}
# Factory constructor
def Komrade(name,pubkey=None,*x,**y):
def Komrade(name=None,pubkey=None,*x,**y):
if issubclass(type(name),Operator): return name
if name and not pubkey and type(name)==bytes:
pubkey=b64enc(name)
name=None
from komrade.backend.the_operator import TheOperator
from komrade.backend.the_telephone import TheTelephone
from komrade.backend.komrades import KomradeX
@ -28,6 +34,7 @@ def Komrade(name,pubkey=None,*x,**y):
if name==TELEPHONE_NAME:
kommie = TheTelephone() #(*x,**y)
else:
print('booting new kommie')
kommie = KomradeX(name,*x,**y)
# print('found!',name,PHONEBOOK[name],PHONEBOOK[name].keychain())
@ -44,26 +51,31 @@ from komrade.constants import OPERATOR_ROUTES
class Operator(Keymaker):
ROUTES = OPERATOR_ROUTES
def __eq__(self,other):
return self.pubkey.data == other.pubkey.data
def __init__(self, name=None, passphrase=DEBUG_DEFAULT_PASSPHRASE, pubkey=None, keychain = {}, path_crypt_keys=PATH_CRYPT_CA_KEYS, path_crypt_data=PATH_CRYPT_CA_DATA):
global PHONEBOOK
# print('booting opertor with ...',name,pubkey,'??')
if pubkey:
# print(pubkey,'pubkey !?')
assert type(pubkey)==bytes
pubkey = b64dec(pubkey)
if keychain.get('pubkey'):
kcpubk=keychain.get('pubkey').data if type(keychain.get('pubkey'))!=bytes else keychain.get('pubkey')
else:
keychain['pubkey']=pubkey #KomradeAsymmetricPublicKey(pubkey)
def __init__(self,
name=None,
pubkey=None,
keychain = {},
path_crypt_keys=PATH_CRYPT_CA_KEYS,
path_crypt_data=PATH_CRYPT_CA_DATA
):
super().__init__(name=name,passphrase=passphrase, keychain=keychain,
path_crypt_keys=path_crypt_keys, path_crypt_data=path_crypt_data)
global PHONEBOOK
# call Keymaker's intro
super().__init__(
name=name,
keychain=keychain,
path_crypt_keys=path_crypt_keys,
path_crypt_data=path_crypt_data
)
# add to phonebook
PHONEBOOK[name]=self
if name: PHONEBOOK[name]=self
if self.pubkey: PHONEBOOK[self.pubkey.data_b64]
@property
@ -95,7 +107,7 @@ class Operator(Keymaker):
return OPERATOR
def compose_msg_to(self,msg,another,incl_from_name=1,incl_to_name=1):
def compose_msg_to(self,msg,another,incl_from_name=True,incl_to_name=True):
if not self.privkey or not self.pubkey:
raise KomradeException('why do I have no pub/privkey pair!?',self,self.name,self.pubkey,self.privkey,self.keychain())
if not another.name or not another.pubkey:
@ -164,7 +176,8 @@ class Operator(Keymaker):
# route it!
self.log(f'Routing msg to {self}.{route}():\n\n{dict_format(msg_obj.data,tab=4)}')
func = getattr(self,route)
new_data = func(**data)
# new_data = func(**data)
new_data = func(msg_obj)
self.log(f'New data was received back from {self}.{route}() route:\b\b{dict_format(new_data,tab=4)}')
msg_obj.msg = msg_obj.msg_d['msg'] = new_data

View File

@ -109,20 +109,6 @@ class TheOperator(Operator):
# return back to phone and back down to chain
return msg_sealed
def send(self,encr_data_b):
self.log(type(encr_data_b),encr_data_b,'sending!')
return encr_data_b
### ROUTES
def does_username_exist(self,name,**data):
pubkey=self.crypt_keys.get(name,prefix='/pubkey/')
self.log(f'looking for {name}, found {pubkey} as pubkey')
return bool(pubkey)
def has_user(self,name=None,pubkey=None):
nm,pk = name,pubkey
if pubkey: pk=self.crypt_keys.get(
@ -138,7 +124,28 @@ class TheOperator(Operator):
# self.log('nms:',name,nm)
return (pubkey and pk) or (name and nm)
def login(self,name,pubkey,secret_login,**data):
def send(self,encr_data_b):
self.log(type(encr_data_b),encr_data_b,'sending!')
return encr_data_b
### ROUTES
def does_username_exist(self,msg_obj):
data=msg_obj.data
name=data.get('name')
pubkey=self.crypt_keys.get(name,prefix='/pubkey/')
self.log(f'looking for {name}, found {pubkey} as pubkey')
return bool(pubkey)
def login(self,msg_obj):
data=msg_obj.data
name=data.get('name')
pubkey=data.get('pubkey')
secret_login=data.get('secret_login')
name=name.encode() if type(name)==str else name
pubkey=pubkey.encode() if type(pubkey)==str else pubkey
secret_login=secret_login.encode() if type(secret_login)==str else secret_login
@ -200,8 +207,11 @@ class TheOperator(Operator):
'status':'Login failed.'
}
def register_new_user(self,name,pubkey,**data):
def register_new_user(self,msg_obj):
# self.log('setting pubkey under name')
data=msg_obj.data
name=data.get('name')
pubkey=data.get('pubkey')
# is user already there?
if self.has_user(name=name,pubkey=pubkey):
@ -269,8 +279,19 @@ class TheOperator(Operator):
# self.log('Operator returning result:',dict_format(res,tab=2))
def deliver_msg(self,msg,to_whom,**data):
pass
def deliver_msg(self,msg_to_op):
data = msg_to_op.data
deliver_to = data.get('deliver_to')
deliver_from = data.get('deliver_from')
deliver_msg = data.get('deliver_msg')
if not deliver_to or not deliver_from or not deliver_msg:
return {'success':'False', 'status':'Invalid input.'}
to_komrade = Komrade(pubkey=deliver_to)
from_komrade = Komrade(pubkey=deliver_from)

View File

@ -85,7 +85,7 @@ class CLI(Logger):
def login(self,name):
print(self,name,self.name,self.komrade,self.loggedin)
# print(self,name,self.name,self.komrade,self.loggedin)
if not name: name=input('name: ')
if not name: return
self.komrade=Komrade(name)
@ -99,7 +99,7 @@ class CLI(Logger):
self.name=None
self.loggedin=False
self.komrade=None
if 'status' in res:
if res and 'status' in res:
print('@Operator: '+res.get('status','?')+'\n')
@property

View File

@ -157,8 +157,8 @@ DEFAULT_USER_SETTINGS = {
SHOW_LOG = 1
SHOW_STATUS = 0
PAUSE_LOGGER = 0
CLEAR_LOGGER = 0
PAUSE_LOGGER = 1
CLEAR_LOGGER = 1
CLI_TITLE = 'KOMRADE'
CLI_FONT = 'clr5x6'#'colossal'