2020-08-12 08:02:51 +00:00
|
|
|
## CONFIG
|
|
|
|
# change this to your external ip address for your server
|
|
|
|
#(needs to be external to allow tor routing)
|
2020-08-21 05:31:42 +00:00
|
|
|
from config import *
|
2020-09-12 18:18:37 +00:00
|
|
|
import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..')))
|
|
|
|
from komrade import *
|
2020-09-22 09:08:20 +00:00
|
|
|
|
2020-09-20 19:34:45 +00:00
|
|
|
import logging
|
|
|
|
logger=logging.getLogger(__name__)
|
2020-09-01 22:41:06 +00:00
|
|
|
|
2020-08-19 13:01:37 +00:00
|
|
|
# monkeypatching the things that asyncio needs
|
|
|
|
import subprocess
|
|
|
|
subprocess.PIPE = -1 # noqa
|
|
|
|
subprocess.STDOUT = -2 # noqa
|
|
|
|
subprocess.DEVNULL = -3 # noqa
|
|
|
|
|
|
|
|
|
2020-08-18 17:25:15 +00:00
|
|
|
import asyncio
|
|
|
|
import os
|
2020-08-19 14:07:12 +00:00
|
|
|
os.environ['KIVY_EVENTLOOP'] = 'asyncio'
|
2020-08-18 17:25:15 +00:00
|
|
|
# loop = asyncio.get_event_loop()
|
|
|
|
# loop.set_debug(True)
|
2020-08-18 14:32:10 +00:00
|
|
|
|
2020-09-23 12:14:12 +00:00
|
|
|
# prefer experimental kivy if possible
|
2020-09-23 18:47:42 +00:00
|
|
|
# sys.path.insert(0,os.path.join(PATH_KOMRADE_LIB,'KivyMD'))
|
2020-09-23 12:14:12 +00:00
|
|
|
import kivymd
|
|
|
|
# print(kivymd.__file__)
|
|
|
|
# exit()
|
|
|
|
|
|
|
|
|
2020-08-12 08:02:51 +00:00
|
|
|
# imports
|
2020-09-23 12:14:12 +00:00
|
|
|
from kivy.uix.screenmanager import *
|
|
|
|
from kivymd.app import *
|
|
|
|
from kivymd.uix.button import *
|
|
|
|
from kivymd.uix.toolbar import *
|
|
|
|
from kivymd.uix.screen import *
|
|
|
|
from kivymd.uix.dialog import *
|
|
|
|
from kivy.lang import *
|
|
|
|
from kivy.uix.boxlayout import *
|
|
|
|
from kivymd.theming import *
|
|
|
|
from kivy.properties import *
|
|
|
|
from kivymd.uix.label import *
|
|
|
|
from kivy.uix.widget import *
|
|
|
|
from kivymd.uix.list import *
|
|
|
|
from kivymd.uix.card import *
|
|
|
|
from kivymd.uix.boxlayout import *
|
|
|
|
from kivy.uix.gridlayout import *
|
|
|
|
from kivy.metrics import *
|
|
|
|
from kivy.properties import *
|
2020-08-03 21:20:38 +00:00
|
|
|
from kivymd.uix.list import * #MDList, ILeftBody, IRightBody, ThreeLineAvatarListItem, TwoLineAvatarListItem, BaseListItem, ImageLeftWidget
|
2020-09-23 12:14:12 +00:00
|
|
|
from kivy.uix.image import *
|
2020-08-06 08:46:51 +00:00
|
|
|
import requests,json
|
2020-09-23 12:14:12 +00:00
|
|
|
from kivy.storage.jsonstore import *
|
|
|
|
from kivy.core.window import *
|
|
|
|
from kivy.core.text import *
|
2020-08-17 20:59:53 +00:00
|
|
|
import shutil,sys
|
2020-09-23 12:14:12 +00:00
|
|
|
from kivy.uix.image import *
|
2020-08-18 06:43:50 +00:00
|
|
|
import sys
|
|
|
|
sys.path.append("..") # Adds higher directory to python modules path.
|
2020-09-01 22:41:06 +00:00
|
|
|
|
2020-09-23 12:14:12 +00:00
|
|
|
from kivy.event import *
|
2020-08-19 13:01:37 +00:00
|
|
|
import threading,asyncio,sys
|
|
|
|
|
2020-08-22 13:27:37 +00:00
|
|
|
# raise Exception(str(Window.size))
|
2020-08-13 07:55:59 +00:00
|
|
|
Window.size = WINDOW_SIZE
|
2020-08-22 13:27:37 +00:00
|
|
|
# Window.fullscreen = True #'auto'
|
2020-08-09 10:32:42 +00:00
|
|
|
|
2020-08-17 16:23:40 +00:00
|
|
|
# with open('log.txt','w') as of:
|
|
|
|
# of.write('### LOG ###\n')
|
2020-08-19 23:26:25 +00:00
|
|
|
def rgb(r,g,b,a=1):
|
|
|
|
return (r/255,g/255,b/255,a)
|
2020-08-10 16:37:42 +00:00
|
|
|
|
2020-08-06 10:24:09 +00:00
|
|
|
class MyLayout(MDBoxLayout):
|
2020-08-03 15:48:47 +00:00
|
|
|
scr_mngr = ObjectProperty(None)
|
2020-08-10 20:38:00 +00:00
|
|
|
post_id = ObjectProperty()
|
2020-08-06 08:46:51 +00:00
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
@property
|
|
|
|
def app(self):
|
|
|
|
if not hasattr(self,'_app'):
|
|
|
|
from kivy.app import App
|
|
|
|
self._app = App.get_running_app()
|
|
|
|
return self._app
|
|
|
|
|
2020-08-19 23:26:25 +00:00
|
|
|
def rgb(self,r,g,b,a=1):
|
|
|
|
return rgb(r,g,b,a=a)
|
|
|
|
|
2020-08-03 15:48:47 +00:00
|
|
|
def change_screen(self, screen, *args):
|
|
|
|
self.scr_mngr.current = screen
|
2020-08-21 17:52:21 +00:00
|
|
|
|
|
|
|
def change_screen_from_uri(self,uri,*args):
|
2020-08-23 13:22:00 +00:00
|
|
|
self.app.uri=uri
|
2020-08-21 17:52:21 +00:00
|
|
|
screen_name = route(uri)
|
|
|
|
self.app.screen = screen_name
|
2020-08-21 21:15:20 +00:00
|
|
|
self.app.log(f'routing to {screen_name}')
|
|
|
|
self.scr_mngr.current = screen_name
|
2020-08-10 20:38:00 +00:00
|
|
|
|
|
|
|
def view_post(self,post_id):
|
|
|
|
self.post_id=post_id
|
|
|
|
self.change_screen('view')
|
2020-08-03 15:48:47 +00:00
|
|
|
|
2020-09-20 19:34:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
from komrade.app.screens.dialog import MDDialog2
|
2020-09-20 19:34:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
class ProgressPopup(MDDialog2): pass
|
2020-09-22 19:34:03 +00:00
|
|
|
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
class MessagePopup(MDDialog2):
|
2020-09-22 19:34:03 +00:00
|
|
|
pass
|
|
|
|
# def __init__(self,*x,**y):
|
|
|
|
# super().__init__(*x,**y)
|
|
|
|
# self.ok_to_continue=False
|
|
|
|
|
|
|
|
# def on_dismiss(self):
|
|
|
|
# if not self.ok_to_continue:
|
|
|
|
# self.ok_to_continue=True
|
|
|
|
# logger.info('ouch!')
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-24 10:40:48 +00:00
|
|
|
|
2020-09-22 19:34:03 +00:00
|
|
|
pass
|
2020-09-23 18:47:42 +00:00
|
|
|
class MessagePopupCard(MDDialog2):
|
2020-09-22 19:34:03 +00:00
|
|
|
def __init__(self,*x,**y):
|
2020-09-26 09:22:10 +00:00
|
|
|
y['color_bg']=rgb(*COLOR_BG)
|
2020-09-23 18:47:42 +00:00
|
|
|
y['type']='custom'
|
2020-09-26 09:22:10 +00:00
|
|
|
y['overlay_color']=rgb(*COLOR_BG)
|
|
|
|
self.color_bg=rgb(*COLOR_BG)
|
2020-09-22 19:34:03 +00:00
|
|
|
super().__init__(*x,**y)
|
|
|
|
self.ok_to_continue=False
|
|
|
|
|
2020-09-24 10:40:48 +00:00
|
|
|
def on_dismiss(self):
|
|
|
|
return True
|
2020-09-23 07:39:41 +00:00
|
|
|
|
2020-09-22 19:34:03 +00:00
|
|
|
def on_touch_down(self,touch):
|
|
|
|
self.ok_to_continue=True
|
|
|
|
logger.info('oof!')
|
|
|
|
# if hasattr(self,'msg_dialog'):
|
|
|
|
# logger.info(str(self.msg_dialog))
|
|
|
|
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
|
|
|
|
class TextInputPopupCard(MDDialog2):
|
|
|
|
def say(self,x):
|
|
|
|
self.ok_to_continue=True
|
|
|
|
self.response=self.field.text
|
|
|
|
return self.response
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self,msg,password=False,input_name='',komrade_name='',*x,**y):
|
|
|
|
self.ok_to_continue=False
|
|
|
|
self.response=None
|
|
|
|
title=msg
|
|
|
|
from komrade.app.screens.login.login import UsernameField,PasswordField,UsernameLayout,UsernameLabel
|
|
|
|
|
|
|
|
self.layout=MDBoxLayout()
|
|
|
|
self.layout.orientation='vertical'
|
|
|
|
self.layout.cols=1
|
|
|
|
self.layout.size_hint=('333sp','222sp')
|
|
|
|
# self.layout.md_bg_color=(1,1,0,1)
|
|
|
|
self.layout.adaptive_height=True
|
|
|
|
self.layout.height=self.layout.minimum_height
|
|
|
|
self.layout.spacing='0sp'
|
|
|
|
self.layout.padding='0sp'
|
|
|
|
|
|
|
|
# self.layout.size=('333sp','333sp')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.field_layout=UsernameLayout()
|
|
|
|
self.field = PasswordField() if password else UsernameField()
|
|
|
|
self.field.line_color_focus=rgb(*COLOR_TEXT)
|
|
|
|
self.field.line_color_normal=rgb(*COLOR_TEXT,a=0.25)
|
|
|
|
self.field.font_name=FONT_PATH
|
2020-09-24 10:40:48 +00:00
|
|
|
self.field.font_size='20sp'
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
self.field_label = UsernameLabel(text='password:' if password else input_name)
|
|
|
|
self.field_label.font_name=FONT_PATH
|
2020-09-24 10:40:48 +00:00
|
|
|
self.field_label.font_size='20sp'
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
if title:
|
|
|
|
self.title_label = UsernameLabel(text=title)
|
|
|
|
self.title_label.halign='center'
|
2020-09-24 10:40:48 +00:00
|
|
|
self.title_label.font_size='20sp'
|
2020-09-23 18:47:42 +00:00
|
|
|
self.title_label.pos_hint={'center_x':0.5}
|
|
|
|
self.title_label.font_name=FONT_PATH
|
|
|
|
#self.field_layout.add_widget(self.title_label)
|
|
|
|
self.layout.add_widget(self.title_label)
|
|
|
|
|
|
|
|
|
2020-09-24 10:40:48 +00:00
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
self.field_layout.add_widget(self.field_label)
|
|
|
|
self.field_layout.add_widget(self.field)
|
|
|
|
self.layout.add_widget(self.field_layout)
|
|
|
|
# do dialog's intro
|
|
|
|
super().__init__(
|
|
|
|
type='custom',
|
|
|
|
text=msg,
|
|
|
|
content_cls=self.layout,
|
|
|
|
buttons=[
|
|
|
|
MDFlatButton(
|
|
|
|
text="cancel",
|
|
|
|
text_color=rgb(*COLOR_TEXT),
|
|
|
|
md_bg_color = (0,0,0,1),
|
|
|
|
theme_text_color='Custom',
|
|
|
|
on_release=self.dismiss,
|
|
|
|
font_name=FONT_PATH
|
|
|
|
),
|
|
|
|
MDFlatButton(
|
|
|
|
text="enter",
|
|
|
|
text_color=rgb(*COLOR_TEXT),
|
|
|
|
md_bg_color = (0,0,0,1),
|
|
|
|
theme_text_color='Custom',
|
|
|
|
on_release=self.say,
|
|
|
|
font_name=FONT_PATH
|
|
|
|
),
|
|
|
|
],
|
|
|
|
color_bg = rgb(*COLOR_CARD)
|
|
|
|
)
|
|
|
|
self.ids.text.text_color=rgb(*COLOR_TEXT)
|
|
|
|
self.ids.text.font_name=FONT_PATH
|
|
|
|
self.size=('333sp','111sp')
|
|
|
|
self.adaptive_height=True
|
|
|
|
|
|
|
|
# wait and show
|
|
|
|
async def open(self,maxwait=666,pulse=0.1):
|
|
|
|
super().open()
|
|
|
|
await asyncio.sleep(pulse)
|
|
|
|
waited=0
|
|
|
|
while not self.ok_to_continue:
|
|
|
|
await asyncio.sleep(pulse)
|
|
|
|
waited+=pulse
|
|
|
|
if waited>maxwait: break
|
|
|
|
# logger.info(f'waiting for {waited} seconds... {self.ok_to_continue} {self.response}')
|
|
|
|
return self.response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BooleanInputPopupCard(MDDialog2):
|
2020-09-23 12:14:12 +00:00
|
|
|
def say_yes(self,x):
|
|
|
|
# logger.info('say_yes got:',str(x))
|
|
|
|
self.ok_to_continue=True
|
|
|
|
self.response=True
|
|
|
|
return self.response
|
|
|
|
def say_no(self,x):
|
|
|
|
# logger.info('say_no got:',str(x))
|
|
|
|
self.ok_to_continue=True
|
|
|
|
self.response=False
|
|
|
|
return self.response
|
|
|
|
|
|
|
|
def __init__(self,msg,*x,**y):
|
|
|
|
self.ok_to_continue=False
|
|
|
|
self.response=None
|
|
|
|
|
|
|
|
|
|
|
|
# do dialog's intro
|
|
|
|
super().__init__(
|
|
|
|
text=msg,
|
|
|
|
buttons=[
|
|
|
|
MDFlatButton(
|
|
|
|
text="no",
|
|
|
|
text_color=rgb(*COLOR_TEXT),
|
|
|
|
md_bg_color = (0,0,0,1),
|
|
|
|
theme_text_color='Custom',
|
|
|
|
on_release=self.say_no,
|
|
|
|
font_name=FONT_PATH
|
|
|
|
),
|
|
|
|
MDFlatButton(
|
|
|
|
text="yes",
|
|
|
|
text_color=rgb(*COLOR_TEXT),
|
|
|
|
md_bg_color = (0,0,0,1),
|
|
|
|
theme_text_color='Custom',
|
|
|
|
on_release=self.say_yes,
|
|
|
|
font_name=FONT_PATH
|
|
|
|
),
|
|
|
|
],
|
|
|
|
color_bg = rgb(*COLOR_CARD)
|
|
|
|
)
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
self.ids.text.text_color=rgb(*COLOR_TEXT)
|
|
|
|
self.ids.text.font_name=FONT_PATH
|
2020-09-23 12:14:12 +00:00
|
|
|
|
|
|
|
# wait and show
|
|
|
|
async def open(self,maxwait=666,pulse=0.1):
|
|
|
|
super().open()
|
|
|
|
await asyncio.sleep(pulse)
|
|
|
|
waited=0
|
|
|
|
while not self.ok_to_continue:
|
|
|
|
await asyncio.sleep(pulse)
|
|
|
|
waited+=pulse
|
|
|
|
if waited>maxwait: break
|
|
|
|
# logger.info(f'waiting for {waited} seconds... {self.ok_to_continue} {self.response}')
|
|
|
|
return self.response
|
|
|
|
|
|
|
|
|
2020-08-06 10:24:09 +00:00
|
|
|
class MyBoxLayout(MDBoxLayout): pass
|
|
|
|
class MyLabel(MDLabel): pass
|
2020-08-03 20:16:30 +00:00
|
|
|
|
2020-08-19 23:26:25 +00:00
|
|
|
class MyToolbar(MDToolbar):
|
|
|
|
action_icon_color = ListProperty()
|
|
|
|
|
|
|
|
def update_action_bar(self, action_bar, action_bar_items):
|
|
|
|
action_bar.clear_widgets()
|
|
|
|
new_width = 0
|
|
|
|
for item in action_bar_items:
|
|
|
|
new_width += dp(48)
|
|
|
|
action_bar.add_widget(
|
|
|
|
MDIconButton(
|
|
|
|
icon=item[0],
|
|
|
|
on_release=item[1],
|
|
|
|
opposite_colors=True,
|
|
|
|
text_color=(self.specific_text_color if not self.action_icon_color else self.action_icon_color),
|
|
|
|
theme_text_color="Custom",
|
|
|
|
)
|
|
|
|
)
|
|
|
|
action_bar.width = new_width
|
|
|
|
|
|
|
|
def update_action_bar_text_colors(self, instance, value):
|
|
|
|
for child in self.ids["left_actions"].children:
|
|
|
|
if not self.action_icon_color:
|
|
|
|
child.text_color = self.specific_text_color
|
|
|
|
else:
|
|
|
|
child.text_color = self.action_icon_color
|
|
|
|
|
|
|
|
for child in self.ids["right_actions"].children:
|
|
|
|
if not self.action_icon_color:
|
|
|
|
child.text_color = self.specific_text_color
|
|
|
|
else:
|
|
|
|
child.text_color = self.action_icon_color
|
2020-08-09 10:32:42 +00:00
|
|
|
|
2020-08-03 16:29:03 +00:00
|
|
|
|
2020-08-06 08:46:51 +00:00
|
|
|
|
2020-08-09 10:32:42 +00:00
|
|
|
|
2020-08-13 17:41:31 +00:00
|
|
|
def draw_background(widget, img_fn='assets/bg.png'):
|
|
|
|
from kivy.core.image import Image as CoreImage
|
|
|
|
from kivy.graphics import Color, Rectangle
|
|
|
|
widget.canvas.before.clear()
|
|
|
|
with widget.canvas.before:
|
|
|
|
Color(.4, .4, .4, 1)
|
|
|
|
texture = CoreImage(img_fn).texture
|
|
|
|
texture.wrap = 'repeat'
|
|
|
|
nx = float(widget.width) / texture.width
|
|
|
|
ny = float(widget.height) / texture.height
|
|
|
|
Rectangle(pos=widget.pos, size=widget.size, texture=texture,
|
|
|
|
tex_coords=(0, 0, nx, 0, nx, ny, 0, ny))
|
|
|
|
|
2020-08-10 20:38:00 +00:00
|
|
|
|
2020-08-18 14:32:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### LOOPER
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
def route(uri):
|
2020-08-21 21:15:20 +00:00
|
|
|
if not '/' in uri: return None
|
|
|
|
prefix=uri.split('/')[1] #,channel,rest = uri.split('/',3)
|
2020-08-18 14:32:10 +00:00
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
mapd = {
|
|
|
|
'inbox':'feed',
|
|
|
|
'outbox':'feed',
|
|
|
|
'login':'login',
|
|
|
|
}
|
|
|
|
return mapd.get(prefix,None)
|
2020-08-18 14:32:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
# DEFAULT_SCREEN = route(DEFAULT_URI)
|
2020-08-18 14:32:10 +00:00
|
|
|
|
2020-09-20 19:34:45 +00:00
|
|
|
class MainApp(MDApp, Logger):
|
2020-08-06 10:24:09 +00:00
|
|
|
title = 'Komrade'
|
2020-08-06 09:43:13 +00:00
|
|
|
logged_in=False
|
|
|
|
login_expiry = 60 * 60 * 24 * 7 # once a week
|
2020-08-13 17:41:31 +00:00
|
|
|
texture = ObjectProperty()
|
2020-09-20 19:34:45 +00:00
|
|
|
uri='/do/login'
|
2020-08-13 17:41:31 +00:00
|
|
|
|
2020-08-19 23:26:25 +00:00
|
|
|
def rgb(self,*_): return rgb(*_)
|
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
def change_screen(self, screen, *args):
|
|
|
|
self.screen=screen
|
|
|
|
self.root.change_screen(screen,*args)
|
|
|
|
|
2020-09-20 19:34:45 +00:00
|
|
|
def get_username(self): return self._name
|
2020-08-21 17:52:21 +00:00
|
|
|
|
2020-08-19 10:29:56 +00:00
|
|
|
@property
|
2020-09-20 19:34:45 +00:00
|
|
|
def crypt(self):
|
|
|
|
if not hasattr(self,'_crypt'):
|
|
|
|
from komrade.backend.crypt import Crypt
|
|
|
|
self._crypt = Crypt(
|
|
|
|
fn=PATH_CRYPT_CA_DATA,
|
|
|
|
encrypt_values=False,
|
|
|
|
)
|
|
|
|
return self._crypt
|
2020-08-16 14:59:36 +00:00
|
|
|
|
2020-08-18 14:32:10 +00:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
self.event_loop_worker = None
|
2020-08-18 17:25:15 +00:00
|
|
|
self.loop=asyncio.get_event_loop()
|
2020-08-19 10:29:56 +00:00
|
|
|
|
|
|
|
# connect to API
|
2020-09-20 19:34:45 +00:00
|
|
|
self.komrade=None
|
|
|
|
self._name=''
|
2020-08-12 06:49:14 +00:00
|
|
|
|
2020-09-01 22:41:06 +00:00
|
|
|
|
2020-08-03 10:25:58 +00:00
|
|
|
def build(self):
|
2020-08-09 10:32:42 +00:00
|
|
|
# bind
|
2020-08-03 16:29:03 +00:00
|
|
|
global app,root
|
2020-08-03 15:48:47 +00:00
|
|
|
app = self
|
2020-08-17 16:23:40 +00:00
|
|
|
|
2020-08-19 10:29:56 +00:00
|
|
|
# load root
|
2020-08-10 21:16:36 +00:00
|
|
|
self.root = root = Builder.load_file('root.kv')
|
2020-08-13 17:41:31 +00:00
|
|
|
draw_background(self.root)
|
2020-08-06 12:55:26 +00:00
|
|
|
|
|
|
|
# edit logo
|
2020-08-19 23:26:25 +00:00
|
|
|
toolbar=root.ids.toolbar
|
|
|
|
toolbar.md_bg_color = root.rgb(*COLOR_TOOLBAR)
|
|
|
|
toolbar.action_icon_color=root.rgb(*COLOR_ICON)
|
|
|
|
logo=toolbar.ids.label_title
|
2020-08-06 12:55:26 +00:00
|
|
|
logo.font_name='assets/Strengthen.ttf'
|
|
|
|
logo.font_size='58dp'
|
|
|
|
logo.pos_hint={'center_y':0.43}
|
2020-08-19 23:26:25 +00:00
|
|
|
logo.text_color=root.rgb(*COLOR_LOGO)
|
2020-08-19 10:29:56 +00:00
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
self.root.change_screen_from_uri(self.uri if self.uri else DEFAULT_URI)
|
2020-09-22 09:08:20 +00:00
|
|
|
|
2020-09-24 10:40:48 +00:00
|
|
|
# build the walker
|
|
|
|
self.walker=MazeWalker(callbacks=self.callbacks)
|
|
|
|
self.torpy_logger = logging.getLogger('torpy')
|
|
|
|
self.torpy_logger.propagate=False
|
|
|
|
self.torpy_logger.addHandler(self.walker)
|
|
|
|
import ipinfo
|
|
|
|
ipinfo_access_token = '90df1baf7c373a'
|
|
|
|
self.ipinfo_handler = ipinfo.getHandler(ipinfo_access_token)
|
|
|
|
|
|
|
|
from komrade.app.screens.map import MapWidget
|
|
|
|
self.map = MapWidget()
|
2020-08-19 10:29:56 +00:00
|
|
|
|
2020-08-03 16:29:03 +00:00
|
|
|
return self.root
|
2020-08-03 10:25:58 +00:00
|
|
|
|
2020-09-20 19:34:45 +00:00
|
|
|
# def boot(self,username):
|
|
|
|
# kommie = Komrade(username)
|
|
|
|
# if self.exists_locally_as_contact()
|
2020-08-18 14:32:10 +00:00
|
|
|
|
2020-09-24 10:40:48 +00:00
|
|
|
@property
|
|
|
|
def callbacks(self):
|
|
|
|
return {
|
|
|
|
'torpy_guard_node_connect':self.callback_on_hop,
|
|
|
|
'torpy_extend_circuit':self.callback_on_hop,
|
|
|
|
}
|
|
|
|
|
|
|
|
async def callback_on_hop(self,rtr):
|
|
|
|
if not hasattr(self,'hops'): self.hops=[]
|
2020-09-26 10:12:16 +00:00
|
|
|
if not hasattr(self,'map') or not self.map:
|
|
|
|
from komrade.app.screens.map import MapWidget
|
|
|
|
self.map=MapWidget()
|
2020-09-24 10:40:48 +00:00
|
|
|
if not self.map.opened:
|
|
|
|
self.map.open()
|
|
|
|
# self.map.draw()
|
|
|
|
|
|
|
|
deets = self.ipinfo_handler.getDetails(rtr.ip)
|
|
|
|
self.hops.append((rtr,deets))
|
|
|
|
lat,long=tuple(float(_) for _ in deets.loc.split(','))
|
|
|
|
flag=f'{deets.city}, {deets.country_name} ({rtr.nickname})'
|
|
|
|
|
|
|
|
self.map.add_point(lat,long,flag)
|
|
|
|
self.map.draw()
|
|
|
|
import asyncio
|
|
|
|
# await asyncio.sleep(2)
|
|
|
|
logger.info('CALLBACK ON HOP: ' + flag)
|
2020-08-18 14:32:10 +00:00
|
|
|
|
2020-08-12 06:49:14 +00:00
|
|
|
def load_store(self):
|
|
|
|
if not self.store.exists('user'): return
|
|
|
|
userd=self.store.get('user')
|
2020-08-21 17:52:21 +00:00
|
|
|
if not userd: return
|
2020-08-06 08:46:51 +00:00
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
self.username = userd.get('username','')
|
2020-09-26 09:22:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def clear_widget_tree(self,widget_type,widget=None):
|
|
|
|
if not widget: widget=self.root
|
|
|
|
for widg in widget.children:
|
|
|
|
if hasattr(widg,'children') and widg.children:
|
|
|
|
self.clear_widget_tree(widget_type,widget=widg)
|
|
|
|
|
|
|
|
self.log(widg,type(widg),widget_type,issubclass(type(widg),widget_type))
|
|
|
|
if issubclass(type(widg),widget_type):
|
|
|
|
self.remove_widget(widg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
|
2020-09-01 22:41:06 +00:00
|
|
|
|
|
|
|
|
2020-08-19 19:33:25 +00:00
|
|
|
async def upload(self,filename,file_id=None):
|
2020-08-19 10:29:56 +00:00
|
|
|
self.log('uploading filename:',filename)
|
2020-08-19 19:33:25 +00:00
|
|
|
rdata=await self.api.upload(filename,file_id=file_id)
|
2020-08-19 10:29:56 +00:00
|
|
|
self.log('upload result:',rdata)
|
2020-08-17 20:40:48 +00:00
|
|
|
if rdata is not None:
|
|
|
|
rdata['success']='File uploaded'
|
|
|
|
return rdata
|
|
|
|
return {'error':'Upload failed'}
|
2020-08-12 19:23:23 +00:00
|
|
|
|
2020-08-19 19:33:25 +00:00
|
|
|
async def download(self,file_id,output_fn=None):
|
2020-08-19 10:29:56 +00:00
|
|
|
self.log('downloading:',file_id)
|
2020-08-19 19:33:25 +00:00
|
|
|
file_dat = await self.api.download(file_id)
|
2020-08-20 11:48:26 +00:00
|
|
|
self.log('file_dat =',file_dat)
|
2020-08-17 22:06:31 +00:00
|
|
|
if not output_fn:
|
|
|
|
file_id=file_dat['id']
|
|
|
|
file_ext=file_dat['ext']
|
|
|
|
output_fn=os.path.join('cache',file_id[:3]+'/'+file_id[3:]+'.'+file_ext)
|
2020-08-12 19:23:23 +00:00
|
|
|
|
2020-08-17 22:06:31 +00:00
|
|
|
output_dir=os.path.dirname(output_fn)
|
|
|
|
if not os.path.exists(output_dir): os.makedirs(output_dir)
|
|
|
|
|
|
|
|
with open(output_fn,'wb') as of:
|
|
|
|
for data_piece in file_dat['parts_data']:
|
|
|
|
if data_piece is not None:
|
|
|
|
of.write(data_piece)
|
2020-08-12 19:23:23 +00:00
|
|
|
|
2020-08-22 20:11:19 +00:00
|
|
|
async def post(self, content='', file_id=None, file_ext=None, anonymous=False,channel='world'):
|
2020-08-17 22:06:31 +00:00
|
|
|
#timestamp=time.time()
|
|
|
|
jsond={}
|
|
|
|
#jsond['timestamp']=
|
|
|
|
if content: jsond['content']=str(content)
|
|
|
|
if file_id: jsond['file_id']=str(file_id)
|
|
|
|
if file_ext: jsond['file_ext']=str(file_ext)
|
2020-08-22 21:20:27 +00:00
|
|
|
if channel and channel[0]=='@': channel=channel[1:]
|
2020-08-23 09:59:52 +00:00
|
|
|
self.log(f'''app.post(
|
2020-08-22 06:12:50 +00:00
|
|
|
content={content},
|
|
|
|
file_id={file_id},
|
|
|
|
file_ext={file_ext},
|
|
|
|
anonymous={anonymous},
|
2020-08-22 20:11:19 +00:00
|
|
|
channel={channel},
|
2020-08-22 06:12:50 +00:00
|
|
|
[username={self.username}]'''
|
|
|
|
)
|
2020-08-17 22:06:31 +00:00
|
|
|
if not anonymous and self.username:
|
|
|
|
jsond['author']=self.username
|
2020-08-23 11:38:50 +00:00
|
|
|
|
|
|
|
#jsond['channel']=channel
|
2020-08-19 10:29:56 +00:00
|
|
|
self.log('posting:',jsond)
|
2020-08-23 11:38:50 +00:00
|
|
|
res=await self.api.post(jsond,channel = channel)
|
2020-08-17 20:40:48 +00:00
|
|
|
if 'success' in res:
|
|
|
|
self.root.change_screen('feed')
|
|
|
|
return {'post_id':res['post_id']}
|
2020-08-12 19:23:23 +00:00
|
|
|
|
2020-08-12 06:49:14 +00:00
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
@property
|
|
|
|
def keys(self):
|
2020-09-20 19:34:45 +00:00
|
|
|
return self.komrade.contacts()
|
2020-08-12 06:49:14 +00:00
|
|
|
|
2020-08-19 14:07:12 +00:00
|
|
|
async def get_post(self,post_id):
|
2020-09-20 19:34:45 +00:00
|
|
|
return self.komrade.read_post()
|
2020-09-01 22:41:06 +00:00
|
|
|
|
2020-09-20 19:34:45 +00:00
|
|
|
def get_posts(self,uri=b'/inbox/world'):
|
|
|
|
return self.komrade.posts()
|
2020-08-21 07:27:27 +00:00
|
|
|
|
2020-08-12 13:43:57 +00:00
|
|
|
|
2020-08-21 17:52:21 +00:00
|
|
|
async def get_channel_posts(self,channel,prefix='inbox'):
|
|
|
|
# am I allowed to?
|
|
|
|
if not channel in self.keys:
|
|
|
|
self.log('!! tsk tsk dont be nosy')
|
|
|
|
return
|
2020-08-22 14:45:48 +00:00
|
|
|
return await self.get_posts(uri='/'+os.path.join(prefix,channel))
|
2020-08-21 17:52:21 +00:00
|
|
|
|
|
|
|
async def get_channel_inbox(self,channel):
|
|
|
|
return await self.get_channel_posts(channel=channel,prefix='inbox')
|
|
|
|
|
|
|
|
async def get_channel_outbox(self,channel):
|
|
|
|
return await self.get_channel_posts(channel=channel,prefix='outbox')
|
|
|
|
|
2020-09-01 22:41:06 +00:00
|
|
|
async def get_my_posts(self):
|
|
|
|
return await self.persona.read_outbox()
|
2020-08-19 19:33:25 +00:00
|
|
|
|
2020-08-11 13:01:48 +00:00
|
|
|
|
2020-08-19 19:33:25 +00:00
|
|
|
|
|
|
|
### SYNCHRONOUS?
|
2020-08-19 14:07:12 +00:00
|
|
|
def app_func(self):
|
|
|
|
'''This will run both methods asynchronously and then block until they
|
|
|
|
are finished
|
|
|
|
'''
|
|
|
|
# self.other_task = asyncio.ensure_future(self.waste_time_freely())
|
2020-09-20 19:34:45 +00:00
|
|
|
# self.other_task = asyncio.ensure_future(self.api.connect_forever())
|
2020-08-19 14:07:12 +00:00
|
|
|
|
|
|
|
async def run_wrapper():
|
|
|
|
# we don't actually need to set asyncio as the lib because it is
|
|
|
|
# the default, but it doesn't hurt to be explicit
|
|
|
|
await self.async_run() #async_lib='asyncio')
|
|
|
|
print('App done')
|
2020-09-20 19:34:45 +00:00
|
|
|
# self.other_task.cancel()
|
2020-08-19 14:07:12 +00:00
|
|
|
|
2020-09-20 19:34:45 +00:00
|
|
|
# return asyncio.gather(run_wrapper(), self.other_task)
|
|
|
|
asyncio.run(run_wrapper())
|
2020-08-06 08:46:51 +00:00
|
|
|
|
|
|
|
|
2020-08-22 21:20:27 +00:00
|
|
|
|
|
|
|
def open_dialog(self,msg):
|
|
|
|
if not hasattr(self,'dialog') or not self.dialog:
|
|
|
|
self.dialog = ProgressPopup()
|
|
|
|
|
|
|
|
# raise Exception(self.dialog, msg)
|
|
|
|
self.dialog.text=msg
|
|
|
|
self.dialog.open()
|
|
|
|
#stop
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
async def get_input(self,msg,komrade_name='Telephone',get_pass=False,yesno=False,**y):
|
2020-09-23 12:14:12 +00:00
|
|
|
from komrade.app.screens.feed.feed import PostCardInputPopup
|
2020-09-23 07:39:41 +00:00
|
|
|
if hasattr(self,'msg_dialog') and self.msg_dialog:# and hasattr(self.msg_dialog,'card') and self.msg_dialog.card:
|
|
|
|
self.msg_dialog0=self.msg_dialog
|
2020-09-23 18:47:42 +00:00
|
|
|
self.msg_dialog0.dismiss()
|
|
|
|
self.msg_dialog0=None
|
2020-09-23 12:14:12 +00:00
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
if yesno:
|
|
|
|
self.msg_dialog = BooleanInputPopupCard(msg,komrade_name=komrade_name,**y)
|
|
|
|
else:
|
|
|
|
self.msg_dialog = TextInputPopupCard(msg,password=get_pass,komrade_name=komrade_name,**y)
|
2020-09-23 12:14:12 +00:00
|
|
|
|
|
|
|
response = await self.msg_dialog.open()
|
|
|
|
logger.info(f'get_input got user response {response}')
|
2020-09-24 14:42:37 +00:00
|
|
|
async def task():
|
|
|
|
await asyncio.sleep(1)
|
|
|
|
self.msg_dialog.dismiss()
|
|
|
|
asyncio.create_task(task())
|
2020-09-23 18:47:42 +00:00
|
|
|
return response
|
2020-09-23 12:14:12 +00:00
|
|
|
|
2020-09-24 14:42:37 +00:00
|
|
|
async def ring_ring(self,*x,kommie=None,**y):
|
|
|
|
if not kommie: kommie=self.komrade
|
|
|
|
from komrade.app.screens.map import MapWidget
|
|
|
|
self.map=MapWidget()
|
|
|
|
self.map.open()
|
|
|
|
resp_msg_d = await kommie.ring_ring(*x,**y)
|
|
|
|
logger.info('done with ring_ring! ! !')
|
|
|
|
self.map.dismiss()
|
|
|
|
self.map=None
|
|
|
|
return resp_msg_d
|
|
|
|
|
|
|
|
|
|
|
|
async def get_updates(self,*x,kommie=None,**y):
|
|
|
|
if not kommie: kommie=self.komrade
|
|
|
|
from komrade.app.screens.map import MapWidget
|
|
|
|
self.map=MapWidget()
|
|
|
|
self.map.open()
|
|
|
|
await kommie.get_updates(*x,**y)
|
|
|
|
logger.info('done with get_updates! ! !')
|
|
|
|
self.map.dismiss()
|
|
|
|
self.map=None
|
|
|
|
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
|
2020-09-23 07:39:41 +00:00
|
|
|
async def stat(self,msg,komrade_name='Telephone',pause=False,get_pass=False,**y):
|
2020-09-22 19:34:03 +00:00
|
|
|
from komrade.app.screens.feed.feed import PostCard,PostCardPopup
|
|
|
|
if hasattr(self,'msg_dialog') and self.msg_dialog:# and hasattr(self.msg_dialog,'card') and self.msg_dialog.card:
|
|
|
|
self.msg_dialog0=self.msg_dialog
|
2020-09-23 18:47:42 +00:00
|
|
|
self.msg_dialog0.dismiss()
|
2020-09-24 15:21:16 +00:00
|
|
|
self.msg_dialog0.clear_widgets()
|
2020-09-23 18:47:42 +00:00
|
|
|
|
2020-09-22 19:34:03 +00:00
|
|
|
|
|
|
|
self.msg_dialog = MessagePopupCard()
|
2020-09-26 09:22:10 +00:00
|
|
|
# self.root.add_widget(self.msg_dialog)
|
2020-09-22 19:34:03 +00:00
|
|
|
# self.msg_dialog.ids.msg_label.text=msg
|
|
|
|
|
|
|
|
self.msg_dialog.card = postcard = PostCardPopup({
|
|
|
|
'author':komrade_name,
|
|
|
|
'author_prefix':'@',
|
|
|
|
'to_name':'me',
|
|
|
|
'content':msg,
|
|
|
|
'timestamp':time.time(),
|
2020-09-23 07:39:41 +00:00
|
|
|
'author_label_font_size':'18sp',
|
|
|
|
**y
|
2020-09-22 19:34:03 +00:00
|
|
|
},
|
|
|
|
msg_dialog=self.msg_dialog)
|
|
|
|
postcard.font_size='16sp'
|
|
|
|
postcard.size_hint=(None,None)
|
|
|
|
postcard.size=('600sp','600sp')
|
|
|
|
postcard.ok_to_continue=False
|
2020-09-23 07:39:41 +00:00
|
|
|
|
2020-09-22 19:34:03 +00:00
|
|
|
self.msg_dialog.add_widget(postcard)
|
|
|
|
|
2020-09-23 18:47:42 +00:00
|
|
|
self.msg_dialog.open(animation=False)
|
2020-09-22 19:34:03 +00:00
|
|
|
|
|
|
|
if hasattr(self,'msg_dialog0'):
|
|
|
|
self.root.remove_widget(self.msg_dialog0)
|
|
|
|
|
|
|
|
await asyncio.sleep(0.1)
|
|
|
|
while not self.msg_dialog.ok_to_continue:
|
|
|
|
await asyncio.sleep(0.1)
|
|
|
|
# logger.info(str(postcard), postcard.ok_to_continue,'??')
|
|
|
|
# self.msg_dialog.dismiss()
|
2020-09-26 09:22:10 +00:00
|
|
|
self.msg_dialog.remove_widget(postcard)
|
|
|
|
# self.root.remove_widget(self.msg_dialog)
|
|
|
|
# self.root.clear_widgets()
|
|
|
|
self.msg_dialog.card = postcard = self.msg_dialog = None
|
2020-09-22 19:34:03 +00:00
|
|
|
await asyncio.sleep(0.1)
|
|
|
|
return {'success':True, 'status':'Delivered popup message'}
|
|
|
|
|
2020-09-20 19:34:45 +00:00
|
|
|
|
2020-08-22 21:20:27 +00:00
|
|
|
def open_msg_dialog(self,msg):
|
2020-09-22 09:08:20 +00:00
|
|
|
# from screens.post.post import MessagePopup,ProgressPopup
|
2020-08-22 21:20:27 +00:00
|
|
|
if not hasattr(self,'msg_dialog') or not self.msg_dialog:
|
|
|
|
self.msg_dialog = MessagePopup()
|
2020-09-20 19:34:45 +00:00
|
|
|
self.msg_dialog.ids.msg_label.text=msg
|
|
|
|
self.msg_dialog.open()
|
2020-08-22 21:20:27 +00:00
|
|
|
|
|
|
|
def close_dialog(self):
|
|
|
|
if hasattr(self,'dialog'):
|
|
|
|
self.dialog.dismiss()
|
|
|
|
|
|
|
|
def close_msg_dialog(self):
|
|
|
|
if hasattr(self,'msg_dialog'):
|
2020-09-22 09:08:20 +00:00
|
|
|
self.msg_dialog.remove_widget(self.msg_dialog.card)
|
2020-08-22 21:20:27 +00:00
|
|
|
self.msg_dialog.dismiss()
|
2020-09-26 09:22:10 +00:00
|
|
|
self.remove_widget(self.msg_dialog)
|
2020-08-22 21:20:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-24 14:42:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-19 14:07:12 +00:00
|
|
|
if __name__ == '__main__':
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
loop.run_until_complete(MainApp().app_func())
|
|
|
|
loop.close()
|
2020-08-19 10:29:56 +00:00
|
|
|
|
2020-08-18 17:25:15 +00:00
|
|
|
|
|
|
|
|
2020-08-19 14:07:12 +00:00
|
|
|
|
|
|
|
# def main():
|
|
|
|
# # start_logger()
|
|
|
|
# App = MainApp()
|
|
|
|
# App.run()
|
|
|
|
|
|
|
|
|
|
|
|
# if __name__ == '__main__':
|
|
|
|
# # loop = asyncio.get_event_loop()
|
|
|
|
# # asyncio.set_event_loop(loop)
|
|
|
|
# # loop.run_until_complete(main())
|
|
|
|
# # loop.close()
|
|
|
|
# main()
|