diff --git a/app/main.py b/app/main.py index 1a39da2..477a314 100644 --- a/app/main.py +++ b/app/main.py @@ -334,7 +334,7 @@ class MainApp(MDApp): if data_piece is not None: of.write(data_piece) - async def post(self, content='', file_id=None, file_ext=None, anonymous=False): + async def post(self, content='', file_id=None, file_ext=None, anonymous=False,channels=['earth']): #timestamp=time.time() jsond={} #jsond['timestamp']= @@ -343,7 +343,7 @@ class MainApp(MDApp): if file_ext: jsond['file_ext']=str(file_ext) if not anonymous and self.username: jsond['author']=self.username - + jsond['to_channels']=channels self.log('posting:',jsond) res=await self.api.post(jsond) if 'success' in res: @@ -358,13 +358,14 @@ class MainApp(MDApp): async def get_post(self,post_id): return await self.api.get_post(post_id) - async def get_posts(self,uri='/inbox/earth'): + async def get_posts(self,uri='/inbox/aa'): self.log(f'app.get_posts(uri={uri} -> ...') data = await self.api.get_posts(uri) - self.log + self.log('app.get_posts() got back from api.get_posts():',data) newdata=[] for d in data: + self.log('data d:',d) if not 'val' in d: continue newdict = dict(d['val'].items()) newdict['timestamp']=float(d['time']) diff --git a/app/misc.py b/app/misc.py index c7b881f..fef11f6 100644 --- a/app/misc.py +++ b/app/misc.py @@ -84,9 +84,12 @@ Builder.load_string( ) -def get_separator(height): +def get_separator(height,width=None,debug=False): from kivymd.uix.boxlayout import MDBoxLayout - return MDBoxLayout(height=height,size_hint=(None,None)) + x=MDBoxLayout(height=height,size_hint=(None,None)) + # if debug: x.md_bg_color=(1,1,0,1) + if width: x.width=width + return x class MyChip(BoxLayout, ThemableBehavior): diff --git a/app/root.kv b/app/root.kv index 93d0266..e610e23 100644 --- a/app/root.kv +++ b/app/root.kv @@ -75,7 +75,7 @@ MyLayout: background_palette: 'Red' theme_text_color:'Custom' background_hue: '500' - right_action_items: [['card-text-outline', partial(root.change_screen, 'feed')], ['pencil-plus-outline', partial(root.change_screen, 'post')], ['message-outline', partial(root.change_screen, 'messages')], ['bell-outline', partial(root.change_screen, 'notifications')], ['account-circle-outline', partial(root.change_screen, 'profile')]] + right_action_items: [['card-text-outline', partial(root.change_screen, 'feed')], ['pencil-plus-outline', partial(root.change_screen, 'post')], ['message-outline', partial(root.change_screen, 'messages')], ['bell-outline', partial(root.change_screen, 'login')], ['account-circle-outline', partial(root.change_screen, 'profile')]] #left_action_items: [[f"assets/fist2.png", partial(root.change_screen, 'feed')]] font_context: None font_name: f'assets/Strengthen.ttf' diff --git a/app/screens/feed/feed.py b/app/screens/feed/feed.py index ba54029..b09ea50 100644 --- a/app/screens/feed/feed.py +++ b/app/screens/feed/feed.py @@ -79,12 +79,12 @@ class PostCard(MDCard): # self.log('PostCard.cache_img_src =',self.cache_img_src) # pieces - author_section_layout = PostAuthorLayout() - author_label = PostAuthorLabel(text='@'+self.author) - author_label.font_size = '18sp' - author_avatar = PostAuthorAvatar(source='assets/avatar.jpg') #self.img_src) - author_section_layout.add_widget(author_avatar) - author_section_layout.add_widget(author_label) + self.author_section_layout = author_section_layout = PostAuthorLayout() + self.author_label = author_label = PostAuthorLabel(text='@'+self.author) + self.author_label.font_size = '18sp' + self.author_avatar = author_avatar = PostAuthorAvatar(source='assets/avatar.jpg') #self.img_src) + self.author_section_layout.add_widget(author_avatar) + self.author_section_layout.add_widget(author_label) # timestamp timestr='' diff --git a/app/screens/post/post.kv b/app/screens/post/post.kv index 4edb113..e28b1e2 100644 --- a/app/screens/post/post.kv +++ b/app/screens/post/post.kv @@ -170,12 +170,23 @@ spacing:0,0 padding:0,0,0,0 orientation: 'lr-tb' + + +: + on_release: self.change_variable(self.text) - +: + id: drop_item + pos_hint: {'center_x': .5, 'center_y': .5} + # text: 'Item' + #items: ['@'+key for key in app.keys] + font_name: 'assets/font.otf' + #on_release: self.set_item("New Item") # size_hint: None, None + id: 'channelchip' height: "26sp" padding: 0, 0, 0, 0 # text: "" @@ -186,6 +197,8 @@ color: rgb(*COLOR_CARD) theme_text_color: 'Custom' text_color: rgb(*COLOR_TEXT) + # pos_hint: {'center_x':0.5} + size_hint: None,None # MDBoxLayout: # id: box_check diff --git a/app/screens/post/post.py b/app/screens/post/post.py index 19a727e..6865813 100644 --- a/app/screens/post/post.py +++ b/app/screens/post/post.py @@ -1,5 +1,6 @@ from screens.base import ProtectedScreen,BaseScreen from plyer import filechooser +from kivy.uix.button import Button from kivymd.uix.label import MDLabel from kivymd.uix.textfield import MDTextField from kivymd.uix.boxlayout import MDBoxLayout @@ -20,6 +21,8 @@ from misc import * from kivy.animation import Animation from kivy.lang import Builder from kivy.metrics import dp +from kivymd.uix.dropdownitem import MDDropDownItem +from kivymd.uix.menu import MDDropdownMenu from kivy.properties import ( BooleanProperty, ListProperty, @@ -98,7 +101,8 @@ class ChannelChip(MDRoundFlatIconButton): def callback(self): val=self.check if hasattr(self,'check') else False self.check = not val - self.icon='checkbox-blank-outline' if self.check else 'check-box-outline' + self.icon='check-box-outline' if self.check else 'checkbox-blank-outline' + self.parent.parent.parent.parent.to_channels[self.text]=self.check # self.md_bg_color=rgb(*COLOR_INACTIVE) if not self.check else rgb(*COLOR_ACTIVE) # raise Exception(['GOT VALL',val]) pass @@ -164,14 +168,15 @@ class ChannelChip(MDRoundFlatIconButton): # self.callback(self, self.label) - - +class AuthorDropdown(MDDropdownMenu): pass +class SenderMenuItem(MDDropDownItem): pass class PostScreen(ProtectedScreen): post_id = ObjectProperty() def on_pre_enter(self): super().on_pre_enter() + self.to_channels = {} # clear if hasattr(self,'post_status'): self.remove_widget(self.post_status) @@ -179,6 +184,8 @@ class PostScreen(ProtectedScreen): post_json = {'author':self.app.username, 'timestamp':time.time()} self.post_card = post = PostCard(post_json) + self.post_card.add_widget(get_separator('15sp'),1) + self.post_card.add_widget(get_separator('15sp'),1) self.post_textfield = post_TextField = AddPostTextField() post_TextField.line_color_focus=rgb(*COLOR_TEXT) post_TextField.line_color_normal=rgb(*COLOR_TEXT) @@ -186,37 +193,90 @@ class PostScreen(ProtectedScreen): post_TextField.font_name='assets/overpass-mono-regular.otf' post_TextField.hint_text='word?' + self.post_card.author_label.text=self.app.username + # self.post_card.author_section_layout.remove_widget(self.post_card.author_label) + # self.post_card.author_dropdown = AuthorDropdown() + #[self.post_card.author_dropdown.set_item('@'+key) for key in self.app.keys] + + + # for key in self.app.keys: + # btn = Ca + # self.post_card.author_dropdown.add_widget(btn) + + # self.post_card.author_section_layout.add_widget(self.post_card.author_dropdown) + # self.menu.bind(on_release=self.menu_callback) + + #self.post_card.author_dropdown.items = ['@'+key + # self.post_card.author_dropdown.font_name='assets/font.otf' + # self.post_card.author_section_layout.add_widget(self.post_card.author_dropdown,1) + # self.post_card.author_label = AuthorDropdown() + #self.addressee = SelectAddressee(list(self.app.keys.keys())) #post.add_widget(self.addressee) - # post.remove_widget(post.scroller) - self.channel_layout = ChannelLayout() #MDBoxLayout(size_hint=(1,None),orientation='horizontal',cols=3) - # self.channel_layout.orientation='horizontal' - # self.channel_layout.cols=1 - # self.channel_layout.size_hint=(1,None) - # self.channel_layout.adaptive_height=True - # self.channel_layout.adaptive_=True - # self.channel_layout.spacing='20dp' - # self.channel_layout.padding='15dp' - # self.channel_layout.height='300sp' #self.channel_layout.minimum_height + self.fields_values = MDBoxLayout() - post.add_widget(self.channel_layout,1) - self.post_card.to_channels = {} + self.fields_values.orientation='horizontal' + self.fields_values.cols=2 + self.fields_values.size_hint=(1,None) + # self.fields_values.md_bg_color=1,1,0,1 + + + post.add_widget(self.fields_values,2) + # post.remove_widget(post.scroller) + + self.to_label = MDLabel(text="To:",size_hint=(None,None)) + self.to_label.pos_hint={'center_y':0.5} + self.fields_values.add_widget(self.to_label) + self.channel_layout = ChannelLayout() #MDBoxLayout(size_hint=(1,None),orientation='horizontal',cols=3) + self.fields_values.add_widget(self.channel_layout) + + # self.fields_values.add_widget(get_separator('10sp')) + # self.fields_values.add_widget(get_separator('10sp')) + + self.to_label.font_name='assets/font.otf' + # self.to_label.padding=(0,0,0,0) + # self.to_label.spacing=(10,10) + + # self.channel_layout.add_widget(self.to_label) + # post.add_widget(self.channel_layout,1) + + + + # menu_labels = [ + # {"viewclass": "SenderMenuItem", + # "text": "Label1", + # "caller":self.post_card.author_dropdown}, + # {"viewclass": "SenderMenuItem", + # "text": "Label2", + # "caller":self.post_card.author_dropdown}, + # ] + for channel in self.app.keys: chip = ChannelChip() - # chip.ids.icon.width='26sp' + chip.check=False self.log(f'adding channel {channel}') chip.text = '@'+channel - # chip.color=rgb(*COLOR_INACTIVE) - # chip.ids.chiplayout.md_bg_color=chip.color - # chip.width='100sp' chip.font_name='assets/font.otf' chip.md_bg_color=rgb(*COLOR_INACTIVE) + + # chip2= SenderMenuItem() + # chip2.text = '@'+channel + # chip2.font_name='assets/font.otf' + # chip2.caller = self.post_card.author_dropdown + # chip2.md_bg_color=rgb(*COLOR_INACTIVE) + # # self.post_card.author_dropdown.add_widget(chip2) + # self.post_card.author_dropdown.add_widget(chip2) + + # chip.theme_text_color='Custom' # chip.text_color=rgb(*COLOR_INACTIVE) self.channel_layout.add_widget(chip) - self.post_card.to_channels[channel]=False + self.to_channels[channel]=False + # self.post_card.author_dropdown.items = menu_labels + # self.post_card.author_dropdown.width_mult = 4 + post.scroller.remove_widget(post.post_content) @@ -334,6 +394,12 @@ class PostScreen(ProtectedScreen): self.open_msg_dialog(f'Text is currently {lencontent} words long, which is {lendiff} over the maximum text length of {maxlen} words.\n\n({lencontent}/{maxlen})') return + channels = [k[1:] for k,v in self.to_channels.items() if v] + if not channels: + self.log('no place was selected') + # self.='No place was selected' + return + # log('?????????????????'+self.media_uid) # if not hasattr(self,'img_id') and self.upload_button.selection: # log('REUPLOADING') @@ -342,7 +408,7 @@ class PostScreen(ProtectedScreen): async def do_post(): file_id = self.img_id if hasattr(self,'img_id') else None file_ext = self.img_ext if hasattr(self,'img_ext') else None - await self.app.post(content=content, file_id=file_id, file_ext=file_ext) + await self.app.post(content=content, channels = channels, file_id=file_id, file_ext=file_ext) import time self.close_dialog() diff --git a/p2p/api.py b/p2p/api.py index 2ce2802..fe236b9 100644 --- a/p2p/api.py +++ b/p2p/api.py @@ -9,9 +9,9 @@ import asyncio,time # logger.setLevel(logging.DEBUG) sys.path.append('../p2p') # logger.info(os.getcwd(), sys.path) -BSEP=b'\n\n' -BSEP2=b'\t\n' -BSEP3=b'\r\r' +BSEP=b'\n\n\n\n' +BSEP2=b'\t\n\t\n' +BSEP3=b'\r\r\r\r' NODE_SLEEP_FOR=1 try: @@ -139,6 +139,8 @@ class Api(object): key=key_or_keys val = await node.get(key) res = await self.decode_data(val) if decode_data else val + self.log('wtf is val =',val) + self.log('wtf is res =',val) self.log(f'_get({key_or_keys}) --> {res}') return res @@ -213,18 +215,30 @@ class Api(object): return final_packet + + async def decode_data(self,entire_packet_orig,sep=BSEP,private_key=None,sep2=BSEP2): if entire_packet_orig is None: return entire_packet_orig - entire_packet = base64.b64decode(entire_packet_orig) + import binascii + # try: + # entire_packet = base64.b64decode(entire_packet_orig) + # except binascii.Error as e: + # entire_packet = entire_packet_orig + # self.log('!!',e) + entire_packet = entire_packet_orig + + self.log('PACKED =',entire_packet) + self.log('????',type(entire_packet)) self.log(entire_packet) # get data try: - encrypted_payload, decryption_tools = entire_packet.split(sep) - decryption_tools=decryption_tools.split(sep2) - except ValueError: - self.log('!! decode_data() got incorrect format') + encrypted_payload, decryption_tools = split_binary(entire_packet, sep=sep) #entire_packet.split(sep) + decryption_tools=split_binary(decryption_tools,sep=sep2) + except AssertionError as e: + + self.log('!! decode_data() got incorrect format:',e) return entire_packet_orig # ### FIRST LINE OF PROTECTION @@ -378,6 +392,7 @@ class Api(object): # if key_or_keys.startsiwth('/post/'): res = await self.get(key_or_keys,decode_data=decode_data) + self.log('get_json() got from get():',res) #self.log('get_json() got',res) if not res: return None return jsonize_res(res) @@ -518,7 +533,9 @@ class Api(object): async def append_json(self,key,data): - sofar=await self.get_json_val(key) + self.log(f'appending to uri {key}') + sofar=await self.get_json_val(key,decode_data=True) + self.log(f'sofar = {sofar}') if sofar is None: sofar = [] if type(sofar)!=list: sofar=[sofar] if type(data)!=list: data=[data] @@ -602,21 +619,34 @@ class Api(object): - async def post(self,data,to_inbox,add_to_outbox=True): + async def post(self,data,add_to_outbox=True): post_id=get_random_id() - res = await self.set_json('/post/'+post_id, data) - if not res: - self.log('!! error, couldn\'t set post json') - return + tasks = [] + self.log(f'post() added post {post_id}') + task = self.set_json('/post/'+post_id, data) + tasks.append(task) + + # res = await + # if not res: + # self.log('!! error, couldn\'t set post json') + # return # ## add to inbox - self.append_json(f'/inbox/{to_inbox}',post_id) + for channel in data.get('to_channels',[]): + self.log('ADDING TO CHANNEL??',channel) + task=self.append_json(f'/inbox/{channel}',post_id) + tasks.append(task) ## add to outbox if add_to_outbox: un=data.get('author') if un: - await self.append_json(f'/outbox/{un}', post_id) + task = self.append_json(f'/outbox/{un}', post_id) + tasks.append(task) + + self.log('gathering tasks') + res = await asyncio.gather(*tasks) + self.log('done with tasks') if res: asyncio.create_task(self.flush()) @@ -625,11 +655,15 @@ class Api(object): async def get_json_val(self,uri,decode_data=True): res=await self.get_json(uri,decode_data=decode_data) - r=None + self.log('get_json_val() got from get_json():',res) + + r=res if type(res) == dict: r=res.get('val',None) if res is not None else None elif type(res) == list: r=[x.get('val',None) for x in res if x is not None] + elif type(res) == str: + r=json.loads(res) self.log(f'get_json_val() --> {r}') return r @@ -639,8 +673,10 @@ class Api(object): async def get_posts(self,uri='/inbox/earth'): # index = await self.get_json_val('/posts'+uri) self.log(f'api.get_posts(uri={uri}) --> ...') - index = await self.get_json_val(uri,decode_data=True) - self.log('got index?',index) + index = await self.get(uri,decode_data=True) + self.log('first index =',index) + index = json.loads(index) + self.log('got index?',index,type(index)) if index is None: return [] if type(index)!=list: index=[index] @@ -648,7 +684,8 @@ class Api(object): index = [x for x in index if x is not None] ## get full json - return await self.get_json(['/post/'+x for x in index]) + x = await self.get(['/post/'+x for x in index]) + return [y for y in x if y is not None] @@ -800,11 +837,41 @@ def init_entities(usernames = ['earth']): asyncio.run(register(un)) +def split_binary(data, sep=BSEP): + seplen = len(BSEP) + res=[] + stack=None + print('!!',data[:4],seplen,sep) + cutoffs=[] + for i in range(0, len(data)): + seg=data[i:i+seplen] + print(i,seg,sep,stack) + if seg==sep: + # split_piece = data[:i+seplen] + print('!') + cutoff_lasttime = cutoffs[-1][-1] if cutoffs and cutoffs else 0 + cutoff = (cutoff_lasttime-seplen, i) + print(cutoff) + cutoffs.append(cutoff) + stack = data[cutoff[0] if cutoff[0]>0 else 0: cutoff[1]] + print(stack) + res += [stack] + stack = None + + cutoff_lasttime = cutoffs[-1][-1] if cutoffs and cutoffs else 0 + print(cutoff_lasttime) + stack = data[cutoff_lasttime+seplen :] + res+=[stack] + print('RES:',res) + return res if __name__=='__main__': - init_entities() \ No newline at end of file + #init_entities() + + res = split_binary(b'eeeehey||||whatsueep',b'||||') + print(res) \ No newline at end of file