diff --git a/komrade/app/assets/avatars/britney.jpg b/komrade/app/assets/avatars/britney.jpg new file mode 100644 index 0000000..be45094 Binary files /dev/null and b/komrade/app/assets/avatars/britney.jpg differ diff --git a/komrade/app/assets/avatars/britney2.jpg b/komrade/app/assets/avatars/britney2.jpg new file mode 100644 index 0000000..fc13a50 Binary files /dev/null and b/komrade/app/assets/avatars/britney2.jpg differ diff --git a/komrade/app/main.py b/komrade/app/main.py index fe7a2b8..a5b785f 100644 --- a/komrade/app/main.py +++ b/komrade/app/main.py @@ -98,8 +98,27 @@ class MyLayout(MDBoxLayout): self.post_id=post_id self.change_screen('view') + def refresh(self,*x,**yy): + async def go(): + if not hasattr(self.app,'is_logged_in') or not self.app.is_logged_in or not hasattr(self.app,'komrade') or not self.app.komrade: + self.change_screen('login') + self.app.log('changing screen???') + return None + logger.info(f'REFRESH: {self.app.is_logged_in}, {self.app.komrade.name}') + stop + exit() + self.app.log('<--',x,yy) + if not hasattr(self.app,'map') or not self.app.map: + from komrade.app.screens.map import MapWidget + self.app.map=MapWidget() + self.app.map.open() + await self.app.komrade.get_updates() + self.app.map.dismiss() + self.app.map=None + asyncio.create_task(go()) + @@ -614,7 +633,7 @@ class MainApp(MDApp, Logger): return await self.get_channel_posts(channel=channel,prefix='outbox') async def get_my_posts(self): - return await self.persona.read_outbox() + return await self.komrade.posts() diff --git a/komrade/app/root.kv b/komrade/app/root.kv index 7411667..4e9c2b4 100644 --- a/komrade/app/root.kv +++ b/komrade/app/root.kv @@ -236,7 +236,7 @@ MyLayout: theme_text_color:'Custom' background_hue: '500' # right_action_items: [['account-circle-outline', partial(root.change_screen, 'profile')],['card-text', partial(root.change_screen, 'feed')],['message-outline', partial(root.change_screen, 'messages')],['pencil-plus-outline', partial(root.change_screen, 'post')],['exit-run', partial(root.change_screen, 'login')]] - right_action_items: [['home', partial(root.change_screen, 'feed')],['message', partial(root.change_screen, 'messages')],['pencil-plus', partial(root.change_screen, 'post')],['account-circle', partial(root.change_screen, 'profile')],['exit-run', partial(root.change_screen, 'login')]] + right_action_items: [['home-outline', partial(root.change_screen, 'feed')],['message-outline', partial(root.change_screen, 'messages')],['pencil-plus-outline', partial(root.change_screen, 'post')],['account-circle-outline', partial(root.change_screen, 'profile')],['refresh', root.refresh],['exit-run', partial(root.change_screen, 'login')]] #left_action_items: [[f"assets/fist2.png", partial(root.change_screen, 'feed')]] # ['bell-outline', partial(root.change_screen, 'login')] diff --git a/komrade/app/screens/feed/feed.py b/komrade/app/screens/feed/feed.py index 2b617f5..36fdd98 100644 --- a/komrade/app/screens/feed/feed.py +++ b/komrade/app/screens/feed/feed.py @@ -293,7 +293,9 @@ class FeedScreen(ProtectedScreen): lim=25 async def go(): - await self.app.get_updates() + # do not get updates! leave that to refresh button! + # await self.app.get_updates() + posts=self.get_posts() for i,post in enumerate(reversed(posts)): if i>lim: break diff --git a/komrade/app/screens/login/login.py b/komrade/app/screens/login/login.py index f2a9e01..8bd2a34 100644 --- a/komrade/app/screens/login/login.py +++ b/komrade/app/screens/login/login.py @@ -222,6 +222,7 @@ class LoginScreen(BaseScreen): elif kommie.exists_locally_as_contact(): await self.app.stat('This is a contact of yours') self.login_status.text='Komrade exists as a contact of yours.' + # self.app.change_screen('feed') self.app.change_screen('login') else: # await self.app.stat('Account does not exist on hardware, maybe not on server. Try to register?') @@ -277,9 +278,10 @@ class LoginScreen(BaseScreen): await logfunc(f'The first is your "public key", which you can share with anyone. With it, someone can write you an encrypted message.',komrade_name='Keymaker') - await logfunc(f'You can share it by pasting it to someone in a secure message:\n{uri_s}',komrade_name='Keymaker') - await logfunc(f'You can also share it IRL, phone to phone, as a QR code. This is what it will look like.',img_src=fnfn,komrade_name='Keymaker') + + # delete qr! + os.remove(fnfn) # await logfunc(f'(1) {pubkey} -- and -- (2) {privkey}',clear=True,pause=True,komrade_name='Keymaker') @@ -298,9 +300,8 @@ class LoginScreen(BaseScreen): ### PRIVATE KEY - await logfunc(f"(2) Your PRIVATE encryption key, on the other hand, must be stored only on your device hardware: {privkey}") - await logfunc(f"In fact this private encryption is so sensitive we'll encrypt it itself before storing it on your device -- locking the key itself away with a password.",pause=True,use_prefix=False) + # await logfunc(f"In fact this private encryption is so sensitive we'll encrypt it itself before storing it on your device -- locking the key itself away with a password.",pause=True,use_prefix=False) # @HACK FOR NOW @@ -315,17 +316,17 @@ class LoginScreen(BaseScreen): privkey_decr = KomradeSymmetricKeyWithPassphrase(passhash=passhash) print() - await logfunc(f'''We immediately whatever you typed through a 1-way hashing algorithm (SHA-256), scrambling it into (redacted):\n{make_key_discreet_str(passhash)}''',pause=True,clear=False) + # await logfunc(f'''We immediately whatever you typed through a 1-way hashing algorithm (SHA-256), scrambling it into (redacted):\n{make_key_discreet_str(passhash)}''',pause=True,clear=False) privkey_encr = privkey_decr.encrypt(privkey.data) privkey_encr_obj = KomradeEncryptedAsymmetricPrivateKey(privkey_encr) kommie._keychain['privkey_encr']=privkey_encr_obj self.log('My keychain now looks like v2:',dict_format(kommie.keychain())) - await logfunc(f'With this scrambled password we can encrypt your super-sensitive private key, from this:\n{privkey.discreet}to this:\n{privkey_encr_obj.discreet}',pause=True,clear=False) + # await logfunc(f'With this scrambled password we can encrypt your super-sensitive private key, from this:\n{privkey.discreet}to this:\n{privkey_encr_obj.discreet}',pause=True,clear=False) # ### PUBLIC KEY - await logfunc('You must also register your username and public key with Komrade @Operator on the remote server',pause=False,clear=False) + await logfunc('You must now register your username and public key with Komrade @Operator on the remote server.',pause=False,clear=False) await logfunc('Connecting you to the @Operator...',komrade_name='Telephone') @@ -345,15 +346,23 @@ class LoginScreen(BaseScreen): # print() - await logfunc(resp_msg_d.get('status'),komrade_name='Operator',pause=True) + await logfunc(resp_msg_d.get('status'),komrade_name='Telephone',pause=True) if not resp_msg_d.get('success'): - await logfunc('''That's too bad. Cancelling registration for now.''',pause=True,clear=True) + self.app.komrade=None + self.app.is_logged_in=False + self.app.username='' + + # await logfunc('''That's too bad. Cancelling registration for now.''',pause=True,clear=True) + + # self.app.change_screen('feed') + self.app.change_screen('login') return # clear_screen() await logfunc('Great. Komrade @Operator now has your name and public key on file (and nothing else!).',pause=True,clear=True) + kommie.name=resp_msg_d.get('name') @@ -379,7 +388,13 @@ class LoginScreen(BaseScreen): # save qr too: _fnfn=kommie.save_uri_as_qrcode(uri_id) - await logfunc(f'Saving public key, encrypted private key, and login secret to hardware-only database. Also saving public key as QR code to: {_fnfn}.',pause=True,clear=False,use_prefix=False) + # await logfunc(f'Saving public key, encrypted private key, and login secret to hardware-only database. Also saving public key as QR code to: {_fnfn}.',pause=True,clear=False,use_prefix=False) + + await logfunc(f'You can share it by pasting it to someone in a secure message:\n{uri_s}',komrade_name='Keymaker') + + await logfunc(f'You can also share it IRL, phone to phone, as a QR code. It is saved to {fnfn} and looks like this.',img_src=fnfn,komrade_name='Keymaker') + + await logfunc(f"(2) Your PRIVATE encryption key, on the other hand, will be stored encrypted on your device hardware. Do not it this with anyone or across any network whatsoever.") # done! await logfunc(f'Congratulations. Welcome, {kommie}.',pause=True,clear=True) @@ -395,7 +410,7 @@ class LoginScreen(BaseScreen): - await logfunc('returning...') + await logfunc('Returning...') from komrade.app.screens.map import MapWidget if self.app.map: diff --git a/komrade/app/screens/map.py b/komrade/app/screens/map.py index 00b8747..c45dfcd 100644 --- a/komrade/app/screens/map.py +++ b/komrade/app/screens/map.py @@ -59,6 +59,7 @@ class MapWidget(MDDialog2): self.points = [] self.opened=False self.label=None + self.intro_label=None # self.fig = fig = plt.figure(figsize=(20,10)) plt.rcParams["figure.figsize"] = self.figsize @@ -167,6 +168,17 @@ class MapWidget(MDDialog2): # self.img.width=Window.size[0] # self.img.allow_stretch=True + def makelabel(self,txt): + label=MDLabel(text=txt) + label.color=self.color_label #rgb(*color) #self.color_label + label.font_name=FONT_PATH + label.font_size='20sp' + # label.size_hint=(1,1) + label.width=Window.size[0] + label.height='25sp' + label.valign='top' + return label + def add_point(self,lat,long,desc): logger.info(f'adding point? {desc} {lat}, {long}') # plt.text( @@ -207,25 +219,7 @@ class MapWidget(MDDialog2): #if self.label: # self.img.remove_widget(self.label) - def makelabel(txt): - label=MDLabel(text=txt) - label.color=self.color_label #rgb(*color) #self.color_label - label.font_name=FONT_PATH - label.font_size='20sp' - # label.size_hint=(1,1) - label.width=Window.size[0] - label.height='25sp' - label.valign='top' - return label - - - if len(self.points)==1: - intro_label = makelabel( - 'Routing you through the global maze of Tor ...' - ) - self.label_layout.add_widget(intro_label) - - self.label=label=makelabel(desc) + self.label=label=self.makelabel(desc) # label.height='400sp' # label.pos_hint = {'center_y':0.1+(0.1 * len(self.points))} # label.pos = (0.5,0) @@ -240,6 +234,9 @@ class MapWidget(MDDialog2): # wait and show def open(self,maxwait=666,pulse=0.1): self.draw() + if not self.intro_label: + self.intro_label = self.makelabel('Routing you through the global maze of Tor ...') + self.label_layout.add_widget(self.intro_label) super().open() self.opened=True # await asyncio.sleep(pulse) @@ -253,6 +250,7 @@ class MapWidget(MDDialog2): def dismiss(self): super().dismiss() + self.intro_label=None if hasattr(self.layout,'img'): self.layout.remove_widget(self.img) if self.layout: diff --git a/komrade/backend/komrades.py b/komrade/backend/komrades.py index f193748..f37152a 100644 --- a/komrade/backend/komrades.py +++ b/komrade/backend/komrades.py @@ -73,6 +73,7 @@ class KomradeX(Caller): uri=pubkey.data_b64 if self.crypt_keys.get(uri,prefix='/privkey_encr/'): return False + self.log(pubkey,self.name,'???') return True def exists_locally_as_account(self): diff --git a/komrade/backend/operators.py b/komrade/backend/operators.py index 23f7f05..b9743d3 100644 --- a/komrade/backend/operators.py +++ b/komrade/backend/operators.py @@ -283,9 +283,9 @@ class Operator(Keymaker): resp_msg_obj = await get_resp_from(msg_obj.msg_d,caller=caller) self.log('resp_msg_obj <-',str(resp_msg_obj)) - if not resp_msg_obj: - print('!! no response from op !!') - exit() + if not resp_msg_obj or type(resp_msg_obj)==dict and not resp_msg_obj.get('success'): + return {'status':'I cannot reach the @Operator. Perhaps she has stepped out. Please hang up and try again later.','success':False,'res':resp_msg_obj} + # exit() # decrypt if resp_msg_obj.is_encrypted: diff --git a/komrade/backend/the_telephone.py b/komrade/backend/the_telephone.py index 5f16bf3..0b4090a 100644 --- a/komrade/backend/the_telephone.py +++ b/komrade/backend/the_telephone.py @@ -5,6 +5,7 @@ from komrade.backend import * from komrade.backend.phonelines import * from komrade.backend.operators import CALLBACKS import requests +from torpy.cell_socket import TorSocketConnectError # def TheTelephone(*x,**y): @@ -38,7 +39,7 @@ class TheTelephone(Operator): return OPERATOR_API_URL - async def send_and_receive(self,msg_d,**y): + async def send_and_receive(self,msg_d,n_attempts=3,**y): # self.log('send and receive got incoming msg:',msg_d) # assert that people can speak only with operator in their first enclosed message! @@ -72,8 +73,15 @@ class TheTelephone(Operator): # loop = asyncio.get_event_loop() texec = ThreadExecutor() - # phonecall=self.komrade_request(URL) - phonecall = await texec(self.komrade_request, URL) + + for n_attempt in range(n_attempts): + self.log('making first attempt to connect via Tor') + try: + # phonecall=self.komrade_request(URL) + phonecall = await texec(self.komrade_request, URL) + break + except TorSocketConnectError: + pass if phonecall.status_code!=200: self.log('!! error in request',phonecall.status_code,phonecall.text) diff --git a/komrade/constants.py b/komrade/constants.py index 5b7ab30..3591785 100644 --- a/komrade/constants.py +++ b/komrade/constants.py @@ -58,7 +58,7 @@ PATH_REPO = os.path.abspath( ) PATH_GUI = os.path.join(PATH_REPO,'komrade','app') PATH_GUI_ASSETS = os.path.join(PATH_GUI,'assets') -PATH_DEFAULT_AVATAR = os.path.join(PATH_GUI_ASSETS,'avatars','marxbot.png') +PATH_DEFAULT_AVATAR = os.path.join(PATH_GUI_ASSETS,'avatars','britney2.jpg') PATH_REPO = PATH_APP = os.path.abspath(os.path.dirname(__file__))