Merge branch 'app-gui'

decryption-error-fix
quadrismegistus 4 years ago
commit 8b0347eece

@ -0,0 +1,26 @@
export KOMRADE_SHOW_LOG=0
echo "`which python`"
SCRIPTPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
pathvenv=`realpath "$SCRIPTPATH/../venv"`
pathconda=`realpath "$SCRIPTPATH/../../lib/miniconda3"`
echo $SCRIPTPATH
echo $pathvenv
echo $pathconda
source $pathconda/etc/profile.d/conda.sh
export PATH="$pathconda/bin:$PATH"
#echo $PATH
echo "`which conda`"
conda activate
conda activate "$pathvenv"
#echo "`which python`"

@ -8,9 +8,18 @@ export KOMRADE_SHOW_LOG=0
SCRIPTPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source "`which komrade-activate`"
echo "`which komrade-activate`"
# echo "`which pip`"
conda info
path=`realpath "$SCRIPTPATH/../komrade/app/main.py"`
pathvenv=`realpath "$SCRIPTPATH/../../venv/bin/activate"`
source $pathvenv
pathreqs=`realpath "$SCRIPTPATH/../requirements.txt"`
python -m pip install -r "$pathreqs"
# pathvenv=`realpath "$SCRIPTPATH/../../venv/bin/activate"`
# source $pathvenv
python "$path" $*

@ -1 +1 @@
gAN9cQAoWAgAAABPcGVyYXRvcnEBfXECWAYAAABwdWJrZXlxA0MtVUVDMgAAAC1hgN9lAxyIsxYZOs5gwowpdARUV1USe4lzL4CPljTKdAesbmxUcQRzWAkAAABUZWxlcGhvbmVxBX1xBihoA0MtVUVDMgAAAC0P2f2HAoNhL9nipoQ/H+gKWULQQHLqszP/5Afq3THpyDNtqppJcQdYBwAAAHByaXZrZXlxCEMtUkVDMgAAAC3k7DbkAD3PjjYZ65798z6aljzN06lvRY3G1wkOUi6KjjEKDil1cQl1WAgAAABrb21yYWRlc3EKfXELaANDLVVFQzIAAAAtfeN2+gPzW/S3F9stS20ic6W5q1ockOAE6LglnVP8Y0r+iU+StnEMc3Uu
gAN9cQAoWAgAAABPcGVyYXRvcnEBfXECWAYAAABwdWJrZXlxA0MtVUVDMgAAAC0bxo2LAoEjBd2zolM21IdPVglscIHT7Zej01DESrM7a7xsqA4ScQRzWAkAAABUZWxlcGhvbmVxBX1xBihoA0MtVUVDMgAAAC3HJMkiA8dBmuaFcjSspwDzMuzsFQ2XqeUOUUWLM+bP6dBoEYfZcQdYBwAAAHByaXZrZXlxCEMtUkVDMgAAAC1HY+cbAMyEsX5ev9h2K3frWRrP2zISYVpH2jBE+Er7LNHwR96UcQl1WAgAAABrb21yYWRlc3EKfXELaANDLVVFQzIAAAAtqvUigQNGhPzEhUr1azXSzfbfeEmeyfWfK7nE9mSVZzCvqiweiXEMc3Uu

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -1,8 +1,8 @@
#from p2p_api import
PORT_LISTEN = 5969
# #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)]
# # NODES_PRIME = [("128.232.229.63",8467), ("68.66.241.111",8467)]
# NODES_PRIME = [("128.232.229.63",8467)]
@ -14,150 +14,150 @@ NODES_PRIME = [("128.232.229.63",8467)]
DEFAULT_URI='/login/'
import random,platform
HORIZONTAL = True # random.choice([True,True,True,False])
FACTOR=1
WINDOW_SIZE = (1136*FACTOR,640*FACTOR) if HORIZONTAL else (640*FACTOR,1136*FACTOR)
PLAYING_CARDS = (2.5,3.5)
ASPECT_RATIO = PLAYING_CARDS[0]/PLAYING_CARDS[1]
ASPECT_RATIO = 1/ASPECT_RATIO
HEIGHT = 850
if platform.platform().startswith('Linux'):
HEIGHT *= 1.25
WINDOW_SIZE=int(HEIGHT),int(HEIGHT * ASPECT_RATIO)
BG_IMG='assets/bg-brown.png'
grass=(201,203,163)
russiangreen = (109,140,96)
huntergreen = (67,92,61)
kombugreen = (49,67,45)
pinetreegreen = (29,40,27)
junglegreen = (15, 21, 14)
browncoffee=(77, 42, 34)
rootbeer=(38, 7, 1)
blackbean=(61, 12, 2)
burntumber=(132, 55, 34)
brownsugar=(175, 110, 81)
antiquebrass= (198, 144, 118)
royalbrown=(94, 55, 46)
bole=(113, 65, 55)
liver= (110, 56, 31)
bistre=(58, 33, 14)
bistre2=(43, 21, 7)
skin1=(89, 47, 42)
skin2=(80, 51, 53)
skin3=(40, 24, 26)
grullo=177, 158, 141
smokyblack=33, 14, 0
liverchestnut=148, 120, 96
ashgray=196, 199, 188
livchestnut2=156, 106, 73
beaver=165, 134, 110
rawumber=120, 95, 74
persianred=202,52,51
vermillion=126,25,27
indianred=205,92,92
barnred=124,10,2
maroon=128,0,0
bloodred=98, 23, 8
rust=188, 57, 8
darksienna=34, 9, 1
yellowcrayola=246, 170, 28
darkred=148, 27, 12
rosewood=94, 11, 21
redviolet=144, 50, 61
bone=217, 202, 179
bronze=188, 128, 52
shadow=140, 122, 107
orangered=194, 3, 3
# DEFAULT_URI='/login/'
# import random,platform
# HORIZONTAL = True # random.choice([True,True,True,False])
# FACTOR=1
# WINDOW_SIZE = (1136*FACTOR,640*FACTOR) if HORIZONTAL else (640*FACTOR,1136*FACTOR)
# PLAYING_CARDS = (2.5,3.5)
# ASPECT_RATIO = PLAYING_CARDS[0]/PLAYING_CARDS[1]
# ASPECT_RATIO = 1/ASPECT_RATIO
# HEIGHT = 850
# if platform.platform().startswith('Linux'):
# HEIGHT *= 1.25
# WINDOW_SIZE=int(HEIGHT),int(HEIGHT * ASPECT_RATIO)
# BG_IMG='assets/bg-brown.png'
# grass=(201,203,163)
# russiangreen = (109,140,96)
# huntergreen = (67,92,61)
# kombugreen = (49,67,45)
# pinetreegreen = (29,40,27)
# junglegreen = (15, 21, 14)
# browncoffee=(77, 42, 34)
# rootbeer=(38, 7, 1)
# blackbean=(61, 12, 2)
# burntumber=(132, 55, 34)
# brownsugar=(175, 110, 81)
# antiquebrass= (198, 144, 118)
# royalbrown=(94, 55, 46)
# bole=(113, 65, 55)
# liver= (110, 56, 31)
# bistre=(58, 33, 14)
# bistre2=(43, 21, 7)
# skin1=(89, 47, 42)
# skin2=(80, 51, 53)
# skin3=(40, 24, 26)
# grullo=177, 158, 141
# smokyblack=33, 14, 0
# liverchestnut=148, 120, 96
# ashgray=196, 199, 188
# livchestnut2=156, 106, 73
# beaver=165, 134, 110
# rawumber=120, 95, 74
# persianred=202,52,51
# vermillion=126,25,27
# indianred=205,92,92
# barnred=124,10,2
# maroon=128,0,0
# bloodred=98, 23, 8
# rust=188, 57, 8
# darksienna=34, 9, 1
# yellowcrayola=246, 170, 28
# darkred=148, 27, 12
# rosewood=94, 11, 21
# redviolet=144, 50, 61
# bone=217, 202, 179
# bronze=188, 128, 52
# shadow=140, 122, 107
# orangered=194, 3, 3
dutchwhite=229,219,181
# black=(0,0,0)
black=15, 15, 15 #5, 8, 13
eerieblack=23, 22, 20
bistre=58, 38, 24
tuscanred=117, 64, 67
grullo2=154, 136, 115
blackolive=55, 66, 61
dogreen=103, 116, 35
sage=187, 193, 145
alabaster2 = 241, 236, 226
coyotebrown = 138, 93, 61
vandykebrown = 90, 62, 41
darksienna2=55, 6, 23
xiketic=3, 7, 30
rossacorsa=208, 0, 0
raisinblack=38, 34, 34
coffee2=67, 58, 58
rufusred=171, 4, 4
darksienna3=56, 22, 13
black2=0, 20, 39
xanadu=112, 141, 129
jasmine=244, 213, 141
ioe=191, 6, 3
dred=141, 8, 1
caputmort1=74, 36, 25
# SCHEME = 'lgreen'
# SCHEME = 'bronze'
SCHEME = 'dark'
# light green theme?
if SCHEME=='lgreen':
COLOR_TOOLBAR= huntergreen #bone #smokyblack #5,5,5 #russiangreen #pinetreegreen #kombugreen #(12,5,5) #russiangreen
COLOR_BG = grass # russiangreen #(0,73,54)
COLOR_LOGO = coyotebrown # grass#russiangreen #(0,0,0) #(0,0,0) #(151,177,140) #(132,162,118) #(109,140,106)
COLOR_TEXT = black #(255,245,200) #(0,0,0,1) #(241,233,203) #COLOR_ICON #(207,219,204) #(239,235,206) # (194,211,187) # (171,189,163) # (222,224,198) # COLOR_LOGO #(223, 223, 212)
COLOR_CARD = bone #(67,92,61) #(12,9,10)
COLOR_CARD_BORDER = COLOR_CARD
COLOR_ICON=COLOR_LOGO
elif SCHEME=='bronze':
COLOR_TOOLBAR= junglegreen
COLOR_BG = bronze
COLOR_LOGO = rufusred #yellowcrayola #0,0,0
COLOR_TEXT = black
COLOR_CARD = bone
COLOR_CARD_BORDER = COLOR_CARD
COLOR_ICON=COLOR_LOGO
else:
# COLOR_TOOLBAR= black
# COLOR_TOOLBAR=bronze
# COLOR_LOGO = black #bronze #0,0,0
# dutchwhite=229,219,181
# # black=(0,0,0)
# black=15, 15, 15 #5, 8, 13
# eerieblack=23, 22, 20
# bistre=58, 38, 24
# tuscanred=117, 64, 67
# grullo2=154, 136, 115
# blackolive=55, 66, 61
# dogreen=103, 116, 35
# sage=187, 193, 145
# alabaster2 = 241, 236, 226
# coyotebrown = 138, 93, 61
# vandykebrown = 90, 62, 41
# darksienna2=55, 6, 23
# xiketic=3, 7, 30
# rossacorsa=208, 0, 0
# raisinblack=38, 34, 34
# coffee2=67, 58, 58
# rufusred=171, 4, 4
# darksienna3=56, 22, 13
# black2=0, 20, 39
# xanadu=112, 141, 129
# jasmine=244, 213, 141
# ioe=191, 6, 3
# dred=141, 8, 1
# caputmort1=74, 36, 25
# # SCHEME = 'lgreen'
# # SCHEME = 'bronze'
# SCHEME = 'dark'
# # light green theme?
# if SCHEME=='lgreen':
# COLOR_TOOLBAR= huntergreen #bone #smokyblack #5,5,5 #russiangreen #pinetreegreen #kombugreen #(12,5,5) #russiangreen
# COLOR_BG = grass # russiangreen #(0,73,54)
# COLOR_LOGO = coyotebrown # grass#russiangreen #(0,0,0) #(0,0,0) #(151,177,140) #(132,162,118) #(109,140,106)
# COLOR_TEXT = black #(255,245,200) #(0,0,0,1) #(241,233,203) #COLOR_ICON #(207,219,204) #(239,235,206) # (194,211,187) # (171,189,163) # (222,224,198) # COLOR_LOGO #(223, 223, 212)
# COLOR_CARD = bone #(67,92,61) #(12,9,10)
# COLOR_CARD_BORDER = COLOR_CARD
# COLOR_ICON=COLOR_LOGO
# elif SCHEME=='bronze':
# COLOR_TOOLBAR= junglegreen
# COLOR_BG = bronze
# COLOR_LOGO = rufusred #yellowcrayola #0,0,0
# COLOR_TEXT = black
# COLOR_CARD = bone
# COLOR_CARD_BORDER = COLOR_CARD
# COLOR_ICON=COLOR_LOGO
# else:
# # COLOR_TOOLBAR= black
# # COLOR_TOOLBAR=bronze
# # COLOR_LOGO = black #bronze #0,0,0
# COLOR_BG = black
COLOR_BG=bistre
COLOR_TOOLBAR=black
COLOR_LOGO=bronze
COLOR_TEXT = black
COLOR_CARD = bone
COLOR_CARD_BORDER = COLOR_CARD
COLOR_ICON=COLOR_LOGO
COLOR_ACCENT = huntergreen
# # COLOR_BG = black
# COLOR_BG=bistre
# COLOR_TOOLBAR=black
# COLOR_LOGO=bronze
# COLOR_TEXT = black
# COLOR_CARD = bone
# COLOR_CARD_BORDER = COLOR_CARD
# COLOR_ICON=COLOR_LOGO
# COLOR_ACCENT = huntergreen
COLOR_INACTIVE = COLOR_CARD
COLOR_ACTIVE = russiangreen
# COLOR_INACTIVE = COLOR_CARD
# COLOR_ACTIVE = russiangreen

@ -21,41 +21,44 @@ os.environ['KIVY_EVENTLOOP'] = 'asyncio'
# loop = asyncio.get_event_loop()
# loop.set_debug(True)
# prefer experimental kivy if possible
# sys.path.insert(0,os.path.join(PATH_KOMRADE_LIB,'KivyMD'))
import kivymd
# print(kivymd.__file__)
# exit()
# imports
from kivy.uix.screenmanager import Screen,ScreenManager
from kivymd.app import MDApp
from kivymd.uix.button import MDFillRoundFlatButton, MDIconButton
from kivymd.uix.toolbar import MDToolbar
from kivymd.uix.screen import MDScreen
from kivymd.uix.dialog import MDDialog
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivymd.theming import ThemeManager
from kivy.properties import ObjectProperty,ListProperty
import time,os
from collections import OrderedDict
from functools import partial
from kivy.uix.screenmanager import NoTransition
from kivymd.uix.label import MDLabel
from kivy.uix.widget import Widget
from kivymd.uix.list import OneLineListItem
from kivymd.uix.card import MDCard, MDSeparator
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.metrics import dp
from kivy.properties import NumericProperty
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 *
from kivymd.uix.list import * #MDList, ILeftBody, IRightBody, ThreeLineAvatarListItem, TwoLineAvatarListItem, BaseListItem, ImageLeftWidget
from kivy.uix.image import Image, AsyncImage
from kivy.uix.image import *
import requests,json
from kivy.storage.jsonstore import JsonStore
from kivy.core.window import Window
from kivy.core.text import LabelBase
from kivy.storage.jsonstore import *
from kivy.core.window import *
from kivy.core.text import *
import shutil,sys
from kivy.uix.image import Image
from kivy.uix.image import *
import sys
sys.path.append("..") # Adds higher directory to python modules path.
from kivy.event import EventDispatcher
from kivy.event import *
import threading,asyncio,sys
# raise Exception(str(Window.size))
@ -100,13 +103,213 @@ class MyLayout(MDBoxLayout):
from komrade.app.screens.dialog import MDDialog2
class ProgressPopup(MDDialog2): pass
class MessagePopup(MDDialog2):
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!')
pass
class MessagePopupCard(MDDialog2):
def __init__(self,*x,**y):
# y['color_bg']=rgb(*COLOR_CARD)
y['type']='custom'
y['overlay_color']=(0,0,0,0)
super().__init__(*x,**y)
# self.color_bg=rgb(*COLOR_CARD)
self.ok_to_continue=False
def on_dismiss(self):
return True
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))
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
self.field.font_size='20sp'
self.field_label = UsernameLabel(text='password:' if password else input_name)
self.field_label.font_name=FONT_PATH
self.field_label.font_size='20sp'
if title:
self.title_label = UsernameLabel(text=title)
self.title_label.halign='center'
self.title_label.font_size='20sp'
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)
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):
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)
)
self.ids.text.text_color=rgb(*COLOR_TEXT)
self.ids.text.font_name=FONT_PATH
# 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 ProgressPopup(MDDialog): pass
class MessagePopup(MDDialog): pass
class MessagePopupCard(MDDialog): pass
class MyBoxLayout(MDBoxLayout): pass
class MyLabel(MDLabel): pass
@ -240,8 +443,17 @@ class MainApp(MDApp, Logger):
self.root.change_screen_from_uri(self.uri if self.uri else DEFAULT_URI)
# 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()
return self.root
@ -249,6 +461,29 @@ class MainApp(MDApp, Logger):
# kommie = Komrade(username)
# if self.exists_locally_as_contact()
@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=[]
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)
def load_store(self):
if not self.store.exists('user'): return
@ -370,25 +605,93 @@ class MainApp(MDApp, Logger):
self.dialog.open()
#stop
def stat(self,msg,komrade_name='Telephone',pause=False,**y):
from komrade.app.screens.feed.feed import PostCard
if not hasattr(self,'msg_dialog') or not self.msg_dialog:
self.msg_dialog = MessagePopupCard()
# self.msg_dialog.ids.msg_label.text=msg
self.msg_dialog.card = postcard = PostCard({
'author':komrade_name,
'author_prefix':'Komrade @',
'to_name':'me',
'content':msg,
'timestamp':time.time(),
})
postcard.size_hint=(None,None)
postcard.size=('600sp','600sp')
self.msg_dialog.add_widget(postcard)
async def get_input(self,msg,komrade_name='Telephone',get_pass=False,yesno=False,**y):
from komrade.app.screens.feed.feed import PostCardInputPopup
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
self.msg_dialog0.dismiss()
self.msg_dialog0=None
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)
response = await self.msg_dialog.open()
logger.info(f'get_input got user response {response}')
async def task():
await asyncio.sleep(1)
self.msg_dialog.dismiss()
asyncio.create_task(task())
return response
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
self.msg_dialog.open()
time.sleep(5)
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
async def stat(self,msg,komrade_name='Telephone',pause=False,get_pass=False,**y):
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
self.msg_dialog0.dismiss()
self.msg_dialog0.clear_widgets()
self.msg_dialog = MessagePopupCard()
# 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(),
'author_label_font_size':'18sp',
**y
},
msg_dialog=self.msg_dialog)
postcard.font_size='16sp'
postcard.size_hint=(None,None)
postcard.size=('600sp','600sp')
postcard.ok_to_continue=False
self.msg_dialog.add_widget(postcard)
self.msg_dialog.open(animation=False)
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()
# self.msg_dialog.remove_widget(postcard)
# self.msg_dialog.card = postcard = self.msg_dialog = None
await asyncio.sleep(0.1)
return {'success':True, 'status':'Delivered popup message'}
def open_msg_dialog(self,msg):
# from screens.post.post import MessagePopup,ProgressPopup
@ -408,6 +711,11 @@ class MainApp(MDApp, Logger):
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(MainApp().app_func())

@ -27,7 +27,7 @@
pos_hint: {'center_x':0.5, 'center_y':0.5}
size_hint:0.5,0.5
padding:'10dp'
md_bg_color:0,0,0,1
md_bg_color:rgb(*COLOR_BG) #0,0,0,1
canvas:
Color:
rgb: 1,0,0,2
@ -45,6 +45,14 @@
font_name: 'assets/font.otf'
size_hint:1,None
<MapImage>:
canvas:
Color:
rgb: (0, 0, 0, 0)
Rectangle:
texture: self.texture
size: self.width + 20, self.height + 20
pos: self.x - 10, self.y - 10
@ -53,7 +61,7 @@
<ProgressPopup>:
type: "custom"
size_hint: (None, None)
size: ('200dp','200dp')
size: ('333sp','333sp')
# md_bg_color: 0,0,0,1
MDBoxLayout:
@ -135,13 +143,22 @@
pos_hint: {'center_x': .5, 'y': 0}
<BooleanInputPopupCard>:
type: "custom"
size_hint: (None, None)
size: ('200dp','200dp')
md_bg_color: rgb(*COLOR_TEXT)
<MessagePopupCard>:
type: "custom"
size_hint: 1,1
# size: ('300dp','300dp')
# md_bg_color: rgb(*COLOR_CARD)
md_bg_color:0,0,0,1
size:('600sp','600sp')
md_bg_color:0,0,0,0
size:('600sp','100sp')
MDBoxLayout:
id: msg_popup_box_layout
@ -151,8 +168,8 @@
size_hint: (1, 1)
# adaptive_height: True
pos_hint: {"center_x": .5, "center_y": .5}
# md_bg_color: rgb(*COLOR_CARD)
md_bg_color:0,0,0,0
md_bg_color: rgb(*COLOR_CARD)
# md_bg_color:0,0,0,0
height: self.minimum_height
# radius:[20,]
# border_radius:20

@ -27,6 +27,8 @@ class BaseScreen(MDScreen):
def channel(self):
return self.app.channel
def stat(self,*x,**y): return self.app.stat(*x,**y)
# class CardScreen(BaseScreen):

@ -0,0 +1,598 @@
"""
Components/Dialog
=================
.. seealso::
`Material Design spec, Dialogs <https://material.io/components/dialogs>`_
.. rubric:: Dialogs inform users about a task and can contain critical
information, require decisions, or involve multiple tasks.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialogs.png
:align: center
Usage
-----
.. code-block:: python
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog2
KV = '''
FloatLayout:
MDFlatButton:
text: "ALERT DIALOG"
pos_hint: {'center_x': .5, 'center_y': .5}
on_release: app.show_alert_dialog()
'''
class Example(MDApp):
dialog = None
def build(self):
return Builder.load_string(KV)
def show_alert_dialog(self):
if not self.dialog:
self.dialog = MDDialog2(
text="Discard draft?",
buttons=[
MDFlatButton(
text="CANCEL", text_color=self.theme_cls.primary_color
),
MDFlatButton(
text="DISCARD", text_color=self.theme_cls.primary_color
),
],
)
self.dialog.open()
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/alert-dialog.png
:align: center
"""
__all__ = ("MDDialog2",)
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.metrics import dp
from kivy.properties import (
ListProperty,
NumericProperty,
ObjectProperty,
OptionProperty,
StringProperty,
)
from kivy.uix.modalview import ModalView
from kivymd.material_resources import DEVICE_TYPE
from kivymd.theming import ThemableBehavior
from kivymd.uix.button import BaseButton
from kivymd.uix.card import MDSeparator
from kivymd.uix.list import BaseListItem
Builder.load_string(
"""
#:import images_path kivymd.images_path
<BaseDialog>
background: '{}/transparent.png'.format(images_path)
canvas.before:
PushMatrix
RoundedRectangle:
pos: self.pos
size: self.size
radius: [5]
Scale:
origin: self.center
x: root._scale_x
y: root._scale_y
canvas.after:
PopMatrix
<MDDialog2>
MDCard:
id: container
orientation: "vertical"
size_hint_y: None
height: self.minimum_height
elevation: 4
md_bg_color: 0, 0, 0, 0
padding: "24dp", "24dp", "8dp", "8dp"
canvas:
Color:
rgba: root.color_bg #root.theme_cls.bg_dark
RoundedRectangle:
pos: self.pos
size: self.size
radius: root.radius
MDLabel:
id: title
text: root.title
font_style: "H6"
bold: True
markup: True
size_hint_y: None
height: self.texture_size[1]
valign: "top"
BoxLayout:
id: spacer_top_box
size_hint_y: None
height: root._spacer_top
MDLabel:
id: text
text: root.text
font_style: "Body1"
theme_text_color: "Custom"
text_color: root.theme_cls.disabled_hint_text_color
size_hint_y: None
height: self.texture_size[1]
markup: True
ScrollView:
id: scroll
size_hint_y: None
height: root._scroll_height
MDGridLayout:
id: box_items
adaptive_height: True
cols: 1
BoxLayout:
id: spacer_bottom_box
size_hint_y: None
height: self.minimum_height
AnchorLayout:
id: root_button_box
size_hint_y: None
height: "52dp"
anchor_x: "right"
MDBoxLayout:
id: button_box
adaptive_size: True
spacing: "8dp"
"""
)
class BaseDialog(ThemableBehavior, ModalView):
_scale_x = NumericProperty(1)
_scale_y = NumericProperty(1)
class MDDialog2(BaseDialog):
title = StringProperty()
"""
Title dialog.
.. code-block:: python
self.dialog = MDDialog2(
title="Reset settings?",
buttons=[
MDFlatButton(
text="CANCEL", text_color=self.theme_cls.primary_color
),
MDFlatButton(
text="ACCEPT", text_color=self.theme_cls.primary_color
),
],
)
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-title.png
:align: center
:attr:`title` is an :class:`~kivy.properties.StringProperty`
and defaults to `''`.
"""
text = StringProperty()
"""
Text dialog.
.. code-block:: python
self.dialog = MDDialog2(
title="Reset settings?",
text="This will reset your device to its default factory settings.",
buttons=[
MDFlatButton(
text="CANCEL", text_color=self.theme_cls.primary_color
),
MDFlatButton(
text="ACCEPT", text_color=self.theme_cls.primary_color
),
],
)
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-text.png
:align: center
:attr:`text` is an :class:`~kivy.properties.StringProperty`
and defaults to `''`.
"""
radius = ListProperty([7, 7, 7, 7])
color_bg=ListProperty([0,0,0,1])
"""
Dialog corners rounding value.
.. code-block:: python
self.dialog = MDDialog2(
text="Oops! Something seems to have gone wrong!",
radius=[20, 7, 20, 7],
)
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-radius.png
:align: center
:attr:`radius` is an :class:`~kivy.properties.ListProperty`
and defaults to `[7, 7, 7, 7]`.
"""
buttons = ListProperty()
"""
List of button objects for dialog.
Objects must be inherited from :class:`~kivymd.uix.button.BaseButton` class.
.. code-block:: python
self.dialog = MDDialog2(
text="Discard draft?",
buttons=[
MDFlatButton(text="CANCEL"), MDRaisedButton(text="DISCARD"),
],
)
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-buttons.png
:align: center
:attr:`buttons` is an :class:`~kivy.properties.ListProperty`
and defaults to `[]`.
"""
items = ListProperty()
"""
List of items objects for dialog.
Objects must be inherited from :class:`~kivymd.uix.list.BaseListItem` class.
With type 'simple'
-----------------
.. code-block:: python
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivymd.app import MDApp
from kivymd.uix.dialog import MDDialog2
from kivymd.uix.list import OneLineAvatarListItem
KV = '''
<Item>
ImageLeftWidget:
source: root.source
FloatLayout:
MDFlatButton:
text: "ALERT DIALOG"
pos_hint: {'center_x': .5, 'center_y': .5}
on_release: app.show_simple_dialog()
'''
class Item(OneLineAvatarListItem):
divider = None
source = StringProperty()
class Example(MDApp):
dialog = None
def build(self):
return Builder.load_string(KV)
def show_simple_dialog(self):
if not self.dialog:
self.dialog = MDDialog2(
title="Set backup account",
type="simple",
items=[
Item(text="user01@gmail.com", source="user-1.png"),
Item(text="user02@gmail.com", source="user-2.png"),
Item(text="Add account", source="add-icon.png"),
],
)
self.dialog.open()
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-items.png
:align: center
With type 'confirmation'
-----------------------
.. code-block:: python
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog2
from kivymd.uix.list import OneLineAvatarIconListItem
KV = '''
<ItemConfirm>
on_release: root.set_icon(check)
CheckboxLeftWidget:
id: check
group: "check"
FloatLayout:
MDFlatButton:
text: "ALERT DIALOG"
pos_hint: {'center_x': .5, 'center_y': .5}
on_release: app.show_confirmation_dialog()
'''
class ItemConfirm(OneLineAvatarIconListItem):
divider = None
def set_icon(self, instance_check):
instance_check.active = True
check_list = instance_check.get_widgets(instance_check.group)
for check in check_list:
if check != instance_check:
check.active = False
class Example(MDApp):
dialog = None
def build(self):
return Builder.load_string(KV)
def show_confirmation_dialog(self):
if not self.dialog:
self.dialog = MDDialog2(
title="Phone ringtone",
type="confirmation",
items=[
ItemConfirm(text="Callisto"),
ItemConfirm(text="Luna"),
ItemConfirm(text="Night"),
ItemConfirm(text="Solo"),
ItemConfirm(text="Phobos"),
ItemConfirm(text="Diamond"),
ItemConfirm(text="Sirena"),
ItemConfirm(text="Red music"),
ItemConfirm(text="Allergio"),
ItemConfirm(text="Magic"),
ItemConfirm(text="Tic-tac"),
],
buttons=[
MDFlatButton(
text="CANCEL", text_color=self.theme_cls.primary_color
),
MDFlatButton(
text="OK", text_color=self.theme_cls.primary_color
),
],
)
self.dialog.open()
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-confirmation.png
:align: center
:attr:`items` is an :class:`~kivy.properties.ListProperty`
and defaults to `[]`.
"""
type = OptionProperty(
"alert", options=["alert", "simple", "confirmation", "custom"]
)
"""
Dialog type.
Available option are `'alert'`, `'simple'`, `'confirmation'`, `'custom'`.
:attr:`type` is an :class:`~kivy.properties.OptionProperty`
and defaults to `'alert'`.
"""
content_cls = ObjectProperty()
"""
Custom content class.
.. code-block::
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivymd.app import MDApp
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog2
KV = '''
<Content>
orientation: "vertical"
spacing: "12dp"
size_hint_y: None
height: "120dp"
MDTextField:
hint_text: "City"
MDTextField:
hint_text: "Street"
FloatLayout:
MDFlatButton:
text: "ALERT DIALOG"
pos_hint: {'center_x': .5, 'center_y': .5}
on_release: app.show_confirmation_dialog()
'''
class Content(BoxLayout):
pass
class Example(MDApp):
dialog = None
def build(self):
return Builder.load_string(KV)
def show_confirmation_dialog(self):
if not self.dialog:
self.dialog = MDDialog2(
title="Address:",
type="custom",
content_cls=Content(),
buttons=[
MDFlatButton(
text="CANCEL", text_color=self.theme_cls.primary_color
),
MDFlatButton(
text="OK", text_color=self.theme_cls.primary_color
),
],
)
self.dialog.open()
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-custom.png
:align: center
:attr:`content_cls` is an :class:`~kivy.properties.ObjectProperty`
and defaults to `'None'`.
"""
_scroll_height = NumericProperty("28dp")
_spacer_top = NumericProperty("24dp")
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.color_bg = kwargs.get('color_bg',self.theme_cls.bg_dark)
if 'color_bg' in kwargs:
del kwargs['color_bg']
if self.size_hint == [1, 1] and DEVICE_TYPE == "mobile":
self.size_hint = (None, None)
self.width = dp(280)
elif self.size_hint == [1, 1] and DEVICE_TYPE == "desktop":
self.size_hint = (None, None)
self.width = dp(560)
if not self.title:
self._spacer_top = 0
if not self.buttons:
self.ids.root_button_box.height = 0
else:
self.create_buttons()
update_height = False
if self.type in ("simple", "confirmation"):
if self.type == "confirmation":
self.ids.spacer_top_box.add_widget(MDSeparator())
self.ids.spacer_bottom_box.add_widget(MDSeparator())
self.create_items()
if self.type == "custom":
if self.content_cls:
self.ids.container.remove_widget(self.ids.scroll)
self.ids.container.remove_widget(self.ids.text)
self.ids.spacer_top_box.add_widget(self.content_cls)
self.ids.spacer_top_box.padding = (0, "24dp", "16dp", 0)
update_height = True
if self.type == "alert":
self.ids.scroll.bar_width = 0
if update_height:
Clock.schedule_once(self.update_height)
def update_height(self, *_):
self._spacer_top = self.content_cls.height + dp(24)
def on_open(self):
# TODO: Add scrolling text.
self.height = self.ids.container.height
def set_normal_height(self):
self.size_hint_y = 0.8
def get_normal_height(self):
return (
(Window.height * 80 / 100)
- self._spacer_top
- dp(52)
- self.ids.container.padding[1]
- self.ids.container.padding[-1]
- 100
)
def edit_padding_for_item(self, instance_item):
instance_item.ids._left_container.x = 0
instance_item._txt_left_pad = "56dp"
def create_items(self):
self.ids.container.remove_widget(self.ids.text)
height = 0
for item in self.items:
if issubclass(item.__class__, BaseListItem):
height += item.height # calculate height contents
self.edit_padding_for_item(item)
self.ids.box_items.add_widget(item)
if height > Window.height:
self.set_normal_height()
self.ids.scroll.height = self.get_normal_height()
else:
self.ids.scroll.height = height
def create_buttons(self):
for button in self.buttons:
if issubclass(button.__class__, BaseButton):
self.ids.button_box.add_widget(button)

@ -164,7 +164,7 @@
padding: "20dp"
size_hint: (0.75, None)
# size:('800sp','800sp')
# adaptive_height: True
adaptive_height: True
pos_hint: {"center_x": .5, "center_y": .5}
md_bg_color: rgb(*COLOR_CARD)
height: self.minimum_height

@ -1,3 +1,7 @@
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 *
from kivymd.uix.label import MDLabel
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import AsyncImage, Image
@ -13,6 +17,8 @@ from threading import Thread
import asyncio
from misc import *
from kivy.core.window import Window
import logging
logger=logging.getLogger(__name__)
@ -110,14 +116,17 @@ class PostCard(MDCard):
if not self.recipient:
self.recipient=self.app.channel
self.img_id = data.get('file_id','')
self.img_ext = data.get('file_ext','')
self.img_src=self.img_id[:3]+'/'+self.img_id[3:]+'.'+self.img_ext if self.img_id else ''
self.cache_img_src = os.path.join('cache',self.img_src) if self.img_src else ''
self.img_loaded = os.path.exists(self.cache_img_src)
# self.img_id = data.get('file_id','')
# self.img_ext = data.get('file_ext','')
# self.img_src=self.img_id[:3]+'/'+self.img_id[3:]+'.'+self.img_ext if self.img_id else ''
# self.cache_img_src = os.path.join('cache',self.img_src) if self.img_src else ''
self.cache_img_src = self.img_src = data.get('img_src','')
self.img_loaded = self.img_src and os.path.exists(self.img_src)
self.content = data.get('content','')
self.timestamp = data.get('timestamp',None)
self.bind(minimum_height=self.setter('height'))
# self.bind(minimum_height=self.setter('height'))
author_prefix=data.get('author_prefix','@')
author_label_font_size=data.get('author_label_font_size','24sp')
recip_label_font_size=data.get('author_label_font_size','14sp')
@ -142,10 +151,13 @@ class PostCard(MDCard):
if self.recipient:
recip=self.recipient
recip='@'+recip if recip and recip[0].isalpha() else recip
self.author_label.text+='\n[size=14sp]to '+recip+'[/size]'
self.author_label.text+=f'\n[size={recip_label_font_size}]to '+recip+'[/size]'
self.author_label.markup=True
self.author_label.font_size = author_label_font_size
self.author_avatar = author_avatar = PostAuthorAvatar(source=f'assets/avatars/{self.author}.png') #self.img_src)
avatar_img_src = os.path.join(PATH_GUI_ASSETS, 'avatars', f'{self.author}.png')
if not os.path.exists(avatar_img_src):
avatar_img_src=PATH_DEFAULT_AVATAR
self.author_avatar = author_avatar = PostAuthorAvatar(source=avatar_img_src) #self.img_src)
self.author_section_layout.add_widget(author_avatar)
self.author_section_layout.add_widget(author_label)
# self.author_section_layout.add_widget(MDSeparator(height='1sp',size_hint=(None,None)))
@ -242,6 +254,27 @@ class PostCard(MDCard):
#####
class PostCardPopup(PostCard):
def __init__(self,*x,msg_dialog=None,**y):
super().__init__(*x,**y)
self.ok_to_continue=False
self.msg_dialog=msg_dialog
def on_touch_down(self,touch):
# if self.collide_point(*touch.pos):# and not self.ok_to_continue:
# logger.info('ouch!!!')
# The touch has occurred inside the widgets area. Do stuff!
self.ok_to_continue=True
if self.msg_dialog: self.msg_dialog.ok_to_continue=True
return True
class PostCardInputPopup(PostCardPopup):
def on_touch_down(self,touch):
pass
class FeedScreen(BaseScreen):
posts = ListProperty()
@ -253,19 +286,22 @@ class FeedScreen(BaseScreen):
i=0
lim=25
self.app.komrade.get_updates()
posts=self.get_posts()
for i,post in enumerate(reversed(posts)):
if i>lim: break
data = {
'author':post.from_name,
'to_name':post.to_name,
'content':post.msg.get('txt') if type(post.msg)==dict else str(post.msg)
}
post_obj = PostCard(data)
self.posts.append(post_obj)
self.ids.post_carousel.add_widget(post_obj)
async def go():
await self.app.get_updates()
posts=self.get_posts()
for i,post in enumerate(reversed(posts)):
if i>lim: break
data = {
'author':post.from_name,
'to_name':post.to_name,
'content':post.msg.get('txt') if type(post.msg)==dict else str(post.msg)
}
post_obj = PostCard(data)
self.posts.append(post_obj)
self.ids.post_carousel.add_widget(post_obj)
asyncio.create_task(go())
# def on_pre_enter(self):
# self.clear_deck()
# # for i,x

@ -17,7 +17,7 @@
orientation:'vertical'
cols:1
size_hint:None,None
width: '300sp'
width: '333sp'
pos_hint: {'center_x':0.5,'center_y':0.5}
md_bg_color: rgb(*COLOR_CARD)
radius:[20,]
@ -59,7 +59,7 @@
<UsernameLabel>:
theme_text_color: 'Custom'
text_color: rgb(*COLOR_TEXT)
width:'100sp'
width:'150sp'
# adaptive_width: True
size_hint:None,None
# md_bg_color:rgb(*COLOR_TEXT)

@ -23,9 +23,11 @@ class LoginButton(MDRectangleFlatButton): pass
class RegisterButton(MDRectangleFlatButton,Logger):
def enter(self):
un=self.parent.parent.parent.username_field.text
# pw=self.parent.parent.parent.password_field.text
login_screen = self.parent.parent.parent
login_screen.boot(un)
time.sleep(0.1)
asyncio.create_task(login_screen.boot(un))
# logger.info('types',type(self.parent),type(self.parent.parent.parent))
@ -60,7 +62,6 @@ class LoginScreen(BaseScreen):
self.label_title.markup=True
self.label_title.color=rgb(*COLOR_TEXT)
self.label_title.text='Welcome,'
# self.label_title.font_size*=1.5
self.layout.add_widget(get_separator('20sp'))
self.layout.add_widget(self.label_title)
self.layout.add_widget(get_separator('30sp'))
@ -68,7 +69,7 @@ class LoginScreen(BaseScreen):
self.layout_username = UsernameLayout()
self.label_username = UsernameLabel(text="Komrade")
self.label_username = UsernameLabel(text="Komrade @")
self.username_field = UsernameField()
self.username_field.line_color_focus=rgb(*COLOR_TEXT)
@ -82,20 +83,20 @@ class LoginScreen(BaseScreen):
#log(self.username_field)
# self.username_field.text='hello????'
self.layout_password = UsernameLayout()
self.label_password = UsernameLabel(text='password:')
# self.layout_password = UsernameLayout()
# self.label_password = UsernameLabel(text='password:')
self.label_password.font_name='assets/font.otf'
# self.label_password.font_name='assets/font.otf'
self.label_username.font_name='assets/font.otf'
self.password_field = PasswordField()
self.password_field.line_color_focus=rgb(*COLOR_TEXT)
self.password_field.line_color_normal=rgb(*COLOR_TEXT,a=0.25)
self.password_field.font_name='assets/font.otf'
# self.password_field = PasswordField()
# self.password_field.line_color_focus=rgb(*COLOR_TEXT)
# self.password_field.line_color_normal=rgb(*COLOR_TEXT,a=0.25)
# self.password_field.font_name='assets/font.otf'
self.layout_password.add_widget(self.label_password)
self.layout_password.add_widget(self.password_field)
self.layout.add_widget(self.layout_password)
# self.layout_password.add_widget(self.label_password)
# self.layout_password.add_widget(self.password_field)
# self.layout.add_widget(self.layout_password)
self.layout_buttons = LoginButtonLayout()
self.layout.add_widget(get_separator('20sp'))
@ -115,16 +116,18 @@ class LoginScreen(BaseScreen):
self.layout.add_widget(self.login_status)
self.label_title.font_size='18sp'
self.label_password.font_size='18sp'
self.label_username.font_size='20sp'
self.label_title.font_size='24sp'
# self.label_password.font_size='18sp'
self.label_username.font_size='22sp'
self.login_button.font_size='12sp'
self.register_button.font_size='9sp'
self.register_button.text='enter'
self.username_field.font_size='20sp'
self.username_field.font_size='24sp'
self.label_username.padding_x=(10,20)
self.username_field.padding_x=(20,10)
self.username_field.padding_y=(25,0)
# self.username_field.padding_y=(25,0)
self.username_field.pos_hint={'center_y':0.5}
self.label_username.halign='right'
@ -156,23 +159,49 @@ class LoginScreen(BaseScreen):
)
self.dialog.open()
def getpass_func(self,why_msg):
return self.password_field.text
def getpass_func(self,why_msg,passphrase=None):
return self.password_field.text if not passphrase else passphrase
def boot(self,un):
async def boot(self,un,pw=None):
# await self.stat('hello',img_src='/home/ryan/komrade/data/contacts/marxxx.png',komrade_name='Keymaker')
# self.app.stat(
# 'You chose the username '+un
# )
# await self.app.get_input('hello?',get_pass=True,title='gimme your passwrdd')
# await self.app.get_input('hello?',get_pass=False,title='gimme your fav color bitch')
# return
# self.remove_widget(self.layout)
# from screens.map import MapWidget,default_places
# map = MapWidget()
# map.open()
# map.add_point(*default_places['Cambridge'],desc='Cambridge')
# map.draw()
# await asyncio.sleep(1)
# map.add_point(*default_places['San Francisco'],desc='San Francisco')
# map.draw()
# await asyncio.sleep(1)
# map.add_point(*default_places['Reykjavik'],desc='Reykjavik')
# map.draw()
# await asyncio.sleep(1)
# return
# return
kommie = Komrade(un,getpass_func=self.getpass_func)
# self.show_pass_opt()
name=un
from komrade.backend import Komrade
kommie = Komrade(un)
self.log('KOMMIE!?!?',kommie)
self.log('wtf',PATH_CRYPT_CA_KEYS)
logger.info(f'booted kommie: {kommie}')
if kommie.exists_locally_as_account():
pw=await self.app.get_input('Welcome back.',get_pass=True)
kommie.keychain(passphrase=pw)
logger.info(f'updated keychain: {dict_format(kommie.keychain())}')
logger.info(f'is account')
self.login_status.text='You should be able to log into this account.'
# self.login_status.text='You should be able to log into this account.'
if kommie.privkey:
logger.info(f'passkey login succeeded')
self.login_status.text=f'Welcome back, Komrade @{un}'
@ -187,10 +216,16 @@ class LoginScreen(BaseScreen):
# self.layout.add_widget(self.layout_password)
elif kommie.exists_locally_as_contact():
self.login_status.text='Komrade exists as a contact of yours.'
await self.app.stat('This is a contact of yours')
self.login_status.text='Komrade exists as a contact of yours.'
else:
self.login_status.text='Komrade not known on this device. Registering...'
res = kommie.register(logfunc=self.app.stat)
# await self.app.stat('Account does not exist on hardware, maybe not on server. Try to register?')
# self.login_status.text='Komrade not known on this device. Registering...'
### REGISTER
self.remove_widget(self.layout)
res = await self.register(un)
if kommie.privkey:
self.login_status.text='Registered'
self.app.is_logged_in=True
@ -199,4 +234,160 @@ class LoginScreen(BaseScreen):
self.remove_widget(self.layout)
self.app.change_screen('feed')
else:
self.login_status.text = 'Sign up failed...'
self.login_status.text = 'Sign up failed...'
return 1
async def register(self,name):
async def logfunc(*x,**y):
if not 'komrade_name' in y: y['komrade_name']='Keymaker'
await self.app.stat(*x,**y)
kommie = Komrade(name)
# already have it?
if kommie.exists_locally_as_account():
return {'success':False, 'status':'You have already created this account.'}
if kommie.exists_locally_as_contact():
return {'success':False, 'status':'This is already a contact of yours'}
#
await logfunc(f'Hello, this is Komrade @{name}. I would like to join the socialist network.',pause=True,komrade_name=name)
await logfunc(f'Welcome, Komrade @{name}. To help us communicate safely, I have cut for you a matching pair of encryption keys.',pause=True,clear=True,komrade_name='Keymaker')
# ## 2) Make pub public/private keys
from komrade.backend.keymaker import KomradeAsymmetricKey
from komrade.cli.artcode import ART_KEY_PAIR
keypair = KomradeAsymmetricKey()
logger.info('cut keypair!')
pubkey,privkey = keypair.pubkey_obj,keypair.privkey_obj
uri_id = pubkey.data_b64
uri_s = pubkey.data_b64_s
fnfn = kommie.save_uri_as_qrcode(uri_id=uri_id,name=name)
# await logfunc(f'Here. I have cut for you a private and public asymmetric key pair, using the iron-clad Elliptic curve algorithm:',komrade_name='Keymaker')
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')
# await logfunc(f'(1) {pubkey} -- and -- (2) {privkey}',clear=True,pause=True,komrade_name='Keymaker')
# await logfunc(f'(1) You may store your public key both on your device hardware, as well as share it with anyone you wish: {pubkey.data_b64_s}') #\n\nIt will also be stored as a QR code on your device:\n{qr_str}',pause=True,clear=True)
kommie._keychain['pubkey']=pubkey
kommie._keychain['privkey']=privkey
from komrade.utils import dict_format
self.log('My keychain now looks like:' + dict_format(kommie.keychain()))
# return
### 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)
passphrase = await self.app.get_input('Please enter a memorable password.',
get_pass=True
)
passhash = hasher(passphrase)
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)
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}',pause=True,clear=False)
await logfunc(f'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('Connecting you to the @Operator...',komrade_name='Telephone')
## CALL OP WITH PUBKEY
# self.app.open_dialog('Calling @Operator...')
logger.info('got here!')
resp_msg_d = await self.app.ring_ring(
{
'name':name,
'pubkey': pubkey.data,
},
route='register_new_user',
kommie=kommie
)
# self.app.close_dialog()
# print()
await logfunc(resp_msg_d.get('status'),komrade_name='Operator',pause=True)
if not resp_msg_d.get('success'):
await logfunc('''That's too bad. Cancelling registration for now.''',pause=True,clear=True)
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')
pubkey_b = resp_msg_d.get('pubkey')
assert pubkey_b == pubkey.data
uri_id = pubkey.data_b64
sec_login = resp_msg_d.get('secret_login')
# stop
await logfunc(f'''Saving keys to device:''',pause=True)
await logfunc(f'''(1) {pubkey}''',pause=True,use_prefix=False)
await logfunc(f'''(2) {privkey_encr_obj}''',pause=True,use_prefix=False)
await logfunc(f'''(3) [Shared Login Secret with @Operator]\n({make_key_discreet(sec_login)})''',pause=True,use_prefix=False)
# print()
kommie.crypt_keys.set(name, pubkey_b, prefix='/pubkey/')
kommie.crypt_keys.set(uri_id, name, prefix='/name/')
kommie.crypt_keys.set(uri_id,sec_login,prefix='/secret_login/')
# store privkey pieces
kommie.crypt_keys.set(uri_id, privkey_encr_obj.data, prefix='/privkey_encr/')
# just to show we used a passphrase -->
kommie.crypt_keys.set(uri_id, KomradeSymmetricKeyWithPassphrase.__name__, prefix='/privkey_decr/')
# save qr too:
_fnfn=kommie.save_uri_as_qrcode(uri_id)
await logfunc(f'Also saving public key as QR code to: {_fnfn}.',pause=True,clear=False,use_prefix=False)
# done!
await logfunc(f'Congratulations. Welcome, {kommie}.',pause=True,clear=True)
# last minute: get posts
if 'res_posts' in resp_msg_d and resp_msg_d['res_posts'].get('success'):
id2post=resp_msg_d.get('res_posts').get('posts',{})
if id2post:
kommie.log('found starter posts:',list(id2post.keys()))
kommie.save_posts(id2post)
resp_msg_d['status']+=f' You\'ve got {len(id2post)} new posts and 0 new messages.'
await logfunc('returning...')
from komrade.app.screens.map import MapWidget
return resp_msg_d

@ -0,0 +1,282 @@
import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..','..')))
from komrade.app.screens.dialog import MDDialog2
import cartopy
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.gridlayout import MDGridLayout
from kivymd.uix.button import MDFlatButton
from kivymd.uix.label import MDLabel
print('\n'.join(sys.path))
from komrade.constants import *
# from komrade.app.main import rgb
import io
from kivy.core.image import Image as CoreImage
from kivy.uix.image import Image,AsyncImage
from kivy.core.window import Window
from kivy.app import App
import logging
logger=logging.getLogger(__name__)
def rgb(r,g,b,a=1):
return (r/255,g/255,b/255,a)
class MapImage(AsyncImage):
pass
class MapWidget(MDDialog2):
@property
def projection(self):
# return ccrs.PlateCarree()
return ccrs.EckertI()
@property
def figsize(self):
# fig = plt.figure()
# dpi=fig.dpi // 2
dpi=40
width,height=Window.size
return (width//dpi, height//dpi)
# bbox = fig.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
# width, height = bbox.width*fig.dpi, bbox.height*fig.dpi
# return (width,height)
@property
def color_land(self): return rgb(*darksienna3,a=0) #darksienna3)
@property
def color_water(self): return rgb(*russiangreen)
@property
def color_label(self): return rgb(*COLOR_ICON)
@property
def color_marker(self): return rgb(*COLOR_ICON)
@property
def color_line(self): return rgb(*COLOR_ICON)
def __init__(self):
self.last_lat = None
self.last_long = None
self.points = []
self.opened=False
self.label=None
# self.fig = fig = plt.figure(figsize=(20,10))
plt.rcParams["figure.figsize"] = self.figsize
self.ax = ax = plt.axes(
projection=self.projection,
)
# ax.set_extent([-170, 165, -55, 75])
# ax.background_patch.set_facecolor(rgb(*COLOR_CARD)[:3])
# ax.outline_patch.set_facecolor(rgb(*COLOR_CARD)[:3])
# self.ax.stock_img()
# self.ax.coastlines(color=rgb(*COLOR_CARD))
ax.add_feature(cartopy.feature.OCEAN, zorder=0, color=self.color_water,edgecolor=self.color_water)
ax.add_feature(cartopy.feature.LAND, zorder=0, color=self.color_land, edgecolor=self.color_land)
ax.outline_patch.set_visible(False)
ax.background_patch.set_visible(False)
# ax.set_global()
# ax.gridlines()
self.layout=MDBoxLayout()
self.layout.orientation='vertical'
self.layout.cols=1
self.layout.size_hint=(None,None)
self.layout.size=(Window.size[0],Window.size[1]) # ('666sp','666sp')
self.layout.md_bg_color=rgb(*eerieblack) #rgb(*COLOR_BG,a=1)
# self.layout.adaptive_height=True
# self.layout.height=self.layout.minimum_height
self.layout.spacing='0sp'
self.layout.padding='0sp'
self.img=None
self.label_layout=MDGridLayout()
self.label_layout.orientation='vertical'
self.label_layout.cols=1
self.label_layout.row_default_height='25sp'
self.label_layout.row_force_default='25sp'
self.label_layout.rows=10
self.label_layout.pos_hint={'y':0}
self.label_layout.size_hint=(None,None)
self.label_layout.width=Window.size[0]
self.label_layout.height='300sp'
# self.label_layout.size=(Window.size[0],'400sp')
# self.label_layout.size=Window.size # ('666sp','666sp')
# self.layout.add_widget(self.label_layout)
# do dialog's intro
super().__init__(
type='custom',
text='',
content_cls=self.layout,
buttons=[
MDFlatButton(
text="disconnect",
text_color=rgb(*COLOR_TEXT),
md_bg_color = rgb(*eerieblack), #(0,0,0,1),
theme_text_color='Custom',
on_release=self.dismiss,
font_name=FONT_PATH
)
],
color_bg = rgb(*eerieblack), #(0,0,0,1),
overlay_color=(0,0,0,0),
background_color=(0,0,0,0)
)
self.ids.text.text_color=rgb(*COLOR_TEXT)
self.ids.text.font_name=FONT_PATH
self.size=Window.size #('666sp','666sp')
# self.
# self.adaptive_height=True
def draw(self):
from matplotlib import transforms
from PIL import Image as pImage
from PIL import ImageOps
tr = transforms.Affine2D().rotate_deg(90)
# buf = io.BytesIO()
# plt.ion()
odir=f'/home/ryan/komrade/data/maps/'
if not os.path.exists(odir): os.makedirs(odir)
ofn=os.path.join(odir,f't_{len(self.points)}.png')
# plt.gca().invert_yaxis()
plt.savefig(ofn, format='png',transparent=True,pad_inches=0.1,bbox_inches = 'tight')
# flip?
# im = pImage.open(ofn)
# im = im.rotate(90)
# im.save(ofn)
if not self.img:
self.img= AsyncImage(source=ofn)
self.img.background_color=(0,0,0,0)
self.img.overlay_color=(0,0,0,0)
# self.img.texture.flip_horizontal()
self.img.pos_hint={'center_x':0.48,'center_y':0.5}
# self.img.size=Window.size
# self.img.texture = img
self.img.add_widget(self.label_layout,1)
self.layout.add_widget(self.img,1)
else:
self.img.source=ofn
# self.img.size_hint=(1,1)
# self.img.width=Window.size[0]
# self.img.allow_stretch=True
def add_point(self,lat,long,desc):
logger.info(f'adding point? {desc} {lat}, {long}')
# plt.text(
# long+3,
# lat-12,
# desc,
# horizontalalignment='left',
# transform=self.projection
# )
import random
from komrade.constants import ALL_COLORS
color = random.choice(ALL_COLORS)
self.points+=[(lat,long,desc)]
# point
plt.plot(
long,
lat,
'+',
markersize=25,
linewidth=10,
color=self.color_marker,#rgb(*color),
transform=ccrs.Geodetic(),
)
# line
if self.last_lat and self.last_long:
plt.plot(
[self.last_long, long],
[self.last_lat, lat],
color=self.color_line,#rgb(*color), #self.color_line,
linewidth=4, marker='',
transform=ccrs.Geodetic(),
)
desc = '\n'.join('--> '+desc for lat,long,desc in self.points[-1:])
#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)
# label.height='400sp'
# label.pos_hint = {'center_y':0.1+(0.1 * len(self.points))}
# label.pos = (0.5,0)
self.label_layout.add_widget(label)
self.last_lat,self.last_long = lat,long
self.ax.set_global()
# wait and show
def open(self,maxwait=666,pulse=0.1):
self.draw()
super().open()
self.opened=True
# 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
def dismiss(self):
super().dismiss()
if hasattr(self.layout,'img'):
self.layout.remove_widget(self.img)
if self.layout:
self.remove_widget(self.layout)
default_places = {
'Cambridge':(52.205338,0.121817),
'Sydney':(-33.868820,151.209290),
'New York':(40.712776,-74.005974),
'Hong Kong':(22.278300,114.174700),
'Cape Town':(-33.9249, 18.4241),
'San Francisco':(37.774929,-122.419418),
'Honolulu':(21.306944,-157.858337),
'Tokyo':(35.689487,139.691711),
'Ushuaia':(-54.801910,-68.302948),
'Reykjavik':(64.126518,-21.817438)
}
def test_map():
map = MapWidget()
plt.show()
if __name__=='__main__':
test_map()

@ -1,4 +1,6 @@
from screens.base import ProtectedScreen
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 *
class NotificationsScreen(ProtectedScreen): pass

@ -1,3 +1,7 @@
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 *
from screens.base import ProtectedScreen,BaseScreen
from plyer import filechooser
from kivy.uix.button import Button

@ -199,13 +199,11 @@ class ProfileScreen(BaseScreen):
clock_scheduled=None
def make_profile_img(self,width,do_crop=True,circ_img=None,bw=False,circularize=True):
img_src = os.path.join(PATH_GUI_ASSETS, 'avatars', f'{self.app.username}.png')
if not os.path.exists(img_src):
img_src=PATH_DEFAULT_AVATAR
img_src = f'assets/avatars/{self.app.username}.png'
if not os.path.exists(img_src): img_src = 'assets/avatars/marx.png'
circ_img = circularize_img(img_src,width,do_crop=do_crop,bw=bw,circularize=circularize)
avatar_layout = LayoutAvatar()
byte=io.BytesIO(circ_img.read())

@ -12,9 +12,9 @@ class Caller(Operator):
Variant of an Operator which handles local keys and keymaking.
"""
def ring_ring(self,msg,**y):
async def ring_ring(self,msg,**y):
# stop
return super().ring_ring(
return await super().ring_ring(
msg,
to_whom=self.op,
get_resp_from=self.phone.ring_ring,

@ -3,16 +3,17 @@ Storage for both keys and data
"""
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 *
from simplekv.fs import FilesystemStore
from simplekv.memory.redisstore import RedisStore
import redis
# from simplekv.fs import FilesystemStore
# from simplekv.memory.redisstore import RedisStore
# import redis
import hashlib,os
import zlib
from pythemis.exception import ThemisError
# from vedis import Vedis
# from walrus.tusks.rlite import WalrusLite
import hirlite
LOG_GET_SET = 0
LOG_GET_SET = 1
@ -57,8 +58,11 @@ class Crypt(Logger):
self.encryptor_func=encryptor_func
self.decryptor_func=decryptor_func
#self.store = FilesystemStore(self.fn)
self.store = RedisStore(redis.StrictRedis())
# self.store = FilesystemStore(self.fn)
# self.store = RedisStore(redis.StrictRedis())
# self.db = Vedis(self.fn)
# self.db = WalrusLite(self.fn)
self.db = hirlite.Rlite(path=self.fn)
def log(self,*x):
@ -66,6 +70,7 @@ class Crypt(Logger):
super().log(*x)
def hash(self,binary_data):
# return binary_data
return hasher(binary_data,self.secret)
def force_binary(self,k_b):
@ -100,7 +105,9 @@ class Crypt(Logger):
return k_b
def has(self,k,prefix=''):
return bool(self.get(k,prefix=prefix))
got=self.get(k,prefix=prefix)
# self.log('has got',got)
return bool(got)
def set(self,k,v,prefix='',override=False,encrypt=True):
@ -113,8 +120,12 @@ class Crypt(Logger):
v_b=self.package_val(v,encrypt = (self.encrypt_values and encrypt))
if not override:
self.log(f'''Crypt.set(\n\t{k_b}\n\n\t{k_b_hash}\n\n\t{v_b}\n)''')
self.store.put(k_b_hash,v_b)
return True
#self.store.put(k_b_hash,v_b)
#with self.db.transaction():
# self.db[k_b_hash]=v_b
return self.db.command('set',k_b_hash,v_b)
# return True
def exists(self,k,prefix=''):
return self.has(k,prefix=prefix)
@ -129,17 +140,24 @@ class Crypt(Logger):
def delete(self,k,prefix=''):
k_b=self.package_key(k,prefix=prefix)
k_b_hash = self.hash(k_b)
r=self.store.delete(k_b_hash)
return r
with self.db.transaction():
del self.db[k_b_hash]
return True
def get(self,k,prefix=''):
k_b=self.package_key(k,prefix=prefix)
k_b_hash = self.hash(k_b)
try:
v=self.store.get(k_b_hash)
except KeyError:
return None
# v=self.db.get(k_b_hash)
self.log('getting k',k,'with prefix',prefix)
self.log('getting k_b',k_b)
self.log('getting k_b_hash',k_b_hash)
v = self.db.command('get',k_b_hash)
self.log('<--',v)
v_b=self.unpackage_val(v)
return v_b
@ -164,105 +182,27 @@ class CryptList(Crypt): # like inbox
decryptor_func=lambda x: x):
self.crypt=crypt
self.keyname=keyname
self.prefix=prefix
self.encryptor_func=encryptor_func
self.decryptor_func=decryptor_func
self.db=self.crypt.db
self.keyname=self.crypt.package_key(keyname,prefix)
def __repr__(self):
return f"""
(CryptList)
val_b_encr = {self.val_b_encr}
val_b = {self.val_b}
values = {self.values}
"""
@property
def val_b_encr(self):
res = self.crypt.get(
self.keyname,
prefix=self.prefix
)
self.log('res from crypt:',res)
return res
@property
def val_b(self):
val_b_encr=self.val_b_encr
if not val_b_encr: return None
return self.decryptor_func(val_b_encr)
@property
def values(self):
if not hasattr(self,'_values') or not self._values:
val_b=self.val_b
if not val_b: return []
self._values = pickle.loads(val_b)
return self._values
def prepend(self,x_l):
return self.append(x_l,insert=0)
def append(self,x_l,insert=None):
if type(x_l)!=list: x_l=[x_l]
val_l = self.values
self.log('val_l =',val_l)
x_l = [x for x in x_l if not x in set(val_l)]
# print('val_l =',val_l)
for x in x_l:
if insert is not None:
val_l.insert(insert,x)
else:
val_l.append(x)
# print('val_l2 =',val_l)
return self.set(val_l)
def set(self,val_l):
self._values = val_l
val_b = pickle.dumps(val_l)
val_b_encr = self.encryptor_func(val_b)
return self.crypt.set(
self.keyname,
val_b_encr,
prefix=self.prefix,
override=True
)
def remove(self,l):
if type(l)!=list: l=[l]
lset=set(l)
values = [x for x in self.values if x not in lset]
return self.set(values)
class CryptListRedis(Logger):
def __init__(self,keyname,prefix='',**y):
self.redis = redis.StrictRedis()
# self.store = RedisStore(self.redis)
self.keyname=b64enc_s(prefix)+b64enc_s(keyname)
self.log('loading CryptList',keyname,prefix,self.keyname)
def values(self): return list(self.l)
def package_val(self,val):
if type(val)==bytes: val=val.decode()
# return b64enc_s(val)
# if type(val)!=bytes: val=val.encode()
return val
def unpackage_val(self,val):
if type(val)==str: val=val.encode()
# return b64dec(val)
# if type(val)==str: val=val.encode()
return val
def append(self,val):
self.log('<--val',val)
if type(val)==list: return [self.append(x) for x in val]
val_x = self.package_val(val)
res = self.redis.rpush(self.keyname,val_x)
# with self.db.transaction():
# res = self.db.lpush(self.keyname,val_x)
res = self.db.command('rpush',self.keyname,val_x)
self.log('-->',res)
return res
@ -270,13 +210,15 @@ class CryptListRedis(Logger):
self.log('<--val',val)
if type(val)==list: return [self.prepend(x) for x in val]
val_x = self.package_val(val)
res = self.redis.lpush(self.keyname,val_x)
res = self.db.command('lpush',self.keyname,val_x)
self.log('-->',res)
return res
@property
def values(self):
l = self.redis.lrange(self.keyname, 0, -1 )
def values(self):
l = self.db.command('lrange',self.keyname, '0', '-1')
self.log('<-- l',l)
if not l: return []
vals = [self.unpackage_val(x) for x in l]
self.log('-->',vals)
return vals
@ -285,21 +227,29 @@ class CryptListRedis(Logger):
self.log('<--',val)
if type(val)==list: return [self.remove(x) for x in val]
val_x = self.package_val(val)
res = self.redis.lrem(self.keyname, 0, val_x)
self.log('-->',res)
return res
self.db.command('lrem',self.keyname,'0',val_x)
if __name__=='__main__':
crypt = Crypt('testt')
crypt = Crypt(fn='tes22t.db')
print(crypt.set(
'testing22',
b'wooooooboy',
prefix='/test/',
))
print('got back', crypt.get(
'testing22',
prefix='/test/'
))
from komrade import KomradeSymmetricKeyWithPassphrase
key = KomradeSymmetricKeyWithPassphrase()
crypt_list = CryptList(
keyname='MyInbox2',
keyname='MyInbosdx35',
crypt=crypt
)
print(crypt_list.values)
@ -308,10 +258,12 @@ if __name__=='__main__':
# print(crypt_list.append('cool thing 1'))
print(crypt_list.append('#1 baby'))
print(crypt_list.append('Appended'))
print(crypt_list.append('cool thing 0'))
print(crypt_list.prepend('#0 baby'))
print(crypt_list.prepend('Prepended'))
print()
print()
print(crypt_list.remove('cool thing 0'))
print()
print()
print(crypt_list.values)

@ -0,0 +1,319 @@
"""
Storage for both keys and data
"""
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 *
from simplekv.fs import FilesystemStore
from simplekv.memory.redisstore import RedisStore
import redis
import hashlib,os
import zlib
from pythemis.exception import ThemisError
LOG_GET_SET = 0
class Crypt(Logger):
def __init__(self,
name=None,
fn=None,
use_secret=CRYPT_USE_SECRET,
path_secret=PATH_CRYPT_SECRET,
encrypt_values=False,
encryptor_func=None,
decryptor_func=None):
# defaults
if not name and fn: name=os.path.basename(fn).replace('.','_')
self.name,self.fn=name,fn
# use secret? for salting
if use_secret and path_secret:
if not os.path.exists(path_secret):
self.secret = get_random_binary_id()
from komrade.backend.keymaker import make_key_discreet
self.log('shhh! creating secret:',make_key_discreet(self.secret))
with open(path_secret,'wb') as of:
of.write(self.secret)
else:
with open(path_secret,'rb') as f:
self.secret = f.read()
else:
self.secret = b''
self.encrypt_values = encrypt_values
if self.secret and encrypt_values and (not encryptor_func or not decryptor_func):
from komrade.backend.keymaker import KomradeSymmetricKeyWithPassphrase
self.key = KomradeSymmetricKeyWithPassphrase(
passphrase=self.secret
)
encryptor_func = self.key.encrypt
decryptor_func = self.key.decrypt
self.encryptor_func=encryptor_func
self.decryptor_func=decryptor_func
self.store = FilesystemStore(self.fn)
# self.store = RedisStore(redis.StrictRedis())
def log(self,*x):
if LOG_GET_SET:
super().log(*x)
def hash(self,binary_data):
return hasher(binary_data,self.secret)
def force_binary(self,k_b):
if k_b is None: return None
if type(k_b)==str: k_b=k_b.encode()
if type(k_b)!=bytes: k_b=k_b.decode()
return k_b
def package_key(self,k,prefix=''):
if not k: return b''
k_b = self.force_binary(k)
k_b2 = self.force_binary(prefix) + k_b
return k_b2
def package_val(self,k,encrypt=None):
if encrypt is None: encrypt=self.encrypt_values
k_b = self.force_binary(k)
if encrypt:
try:
k_b = self.encryptor_func(k_b)
except ThemisError as e:
self.log('!! ENCRYPTION ERROR:',e)
return k_b
def unpackage_val(self,k_b,encrypt=None):
if encrypt is None: encrypt=self.encrypt_values
if encrypt:
try:
k_b = self.decryptor_func(k_b)
except ThemisError as e:
self.log('!! DECRYPTION ERROR:',e)
return k_b
def has(self,k,prefix=''):
return bool(self.get(k,prefix=prefix))
def set(self,k,v,prefix='',override=False,encrypt=True):
if self.has(k,prefix=prefix) and not override:
self.log(f"I'm afraid I can't let you do that, overwrite someone's data!\n\nat {prefix}{k} = {v}")
return False #(False,None,None)
k_b=self.package_key(k,prefix=prefix)
k_b_hash = self.hash(k_b)
v_b=self.package_val(v,encrypt = (self.encrypt_values and encrypt))
if not override:
self.log(f'''Crypt.set(\n\t{k_b}\n\n\t{k_b_hash}\n\n\t{v_b}\n)''')
self.store.put(k_b_hash,v_b)
return True
def exists(self,k,prefix=''):
return self.has(k,prefix=prefix)
def key2hash(self,k,prefix=''):
return self.hash(
self.package_key(
prefix + k
)
)
def delete(self,k,prefix=''):
k_b=self.package_key(k,prefix=prefix)
k_b_hash = self.hash(k_b)
r=self.store.delete(k_b_hash)
return r
def get(self,k,prefix=''):
k_b=self.package_key(k,prefix=prefix)
k_b_hash = self.hash(k_b)
try:
v=self.store.get(k_b_hash)
except KeyError:
return None
v_b=self.unpackage_val(v)
return v_b
class KeyCrypt(Crypt):
def __init__(self):
return super().__init__(name=PATH_CRYPT_CA_KEYS.replace('.','_'))
class DataCrypt(Crypt):
def __init__(self):
return super().__init__(name=PATH_CRYPT_CA_DATA.replace('.','_'))
class CryptList(Crypt): # like inbox
def __init__(self,
crypt,
keyname,
prefix='',
encryptor_func=lambda x: x,
decryptor_func=lambda x: x):
self.crypt=crypt
self.keyname=keyname
self.prefix=prefix
self.encryptor_func=encryptor_func
self.decryptor_func=decryptor_func
def __repr__(self):
return f"""
(CryptList)
val_b_encr = {self.val_b_encr}
val_b = {self.val_b}
values = {self.values}
"""
@property
def val_b_encr(self):
res = self.crypt.get(
self.keyname,
prefix=self.prefix
)
self.log('res from crypt:',res)
return res
@property
def val_b(self):
val_b_encr=self.val_b_encr
if not val_b_encr: return None
return self.decryptor_func(val_b_encr)
@property
def values(self):
if not hasattr(self,'_values') or not self._values:
val_b=self.val_b
if not val_b: return []
self._values = pickle.loads(val_b)
return self._values
def prepend(self,x_l):
return self.append(x_l,insert=0)
def append(self,x_l,insert=None):
if type(x_l)!=list: x_l=[x_l]
val_l = self.values
self.log('val_l =',val_l)
x_l = [x for x in x_l if not x in set(val_l)]
# print('val_l =',val_l)
for x in x_l:
if insert is not None:
val_l.insert(insert,x)
else:
val_l.append(x)
# print('val_l2 =',val_l)
return self.set(val_l)
def set(self,val_l):
self._values = val_l
val_b = pickle.dumps(val_l)
val_b_encr = self.encryptor_func(val_b)
return self.crypt.set(
self.keyname,
val_b_encr,
prefix=self.prefix,
override=True
)
def remove(self,l):
if type(l)!=list: l=[l]
lset=set(l)
values = [x for x in self.values if x not in lset]
return self.set(values)
# !!!!
# @TODO: CAUSING PROBLEMS
# !!!
class CryptListRedis(Logger):
def __init__(self,keyname,prefix='',**y):
self.redis = redis.StrictRedis()
# self.store = RedisStore(self.redis)
self.keyname=b64enc_s(prefix)+b64enc_s(keyname)
self.log('loading CryptList',keyname,prefix,self.keyname)
def package_val(self,val):
if type(val)==bytes: val=val.decode()
# return b64enc_s(val)
return val
def unpackage_val(self,val):
if type(val)==str: val=val.encode()
# return b64dec(val)
return val
def append(self,val):
self.log('<--val',val)
if type(val)==list: return [self.append(x) for x in val]
val_x = self.package_val(val)
res = self.redis.rpush(self.keyname,val_x)
self.log('-->',res)
return res
def prepend(self,val):
self.log('<--val',val)
if type(val)==list: return [self.prepend(x) for x in val]
val_x = self.package_val(val)
res = self.redis.lpush(self.keyname,val_x)
self.log('-->',res)
return res
@property
def values(self):
l = self.redis.lrange(self.keyname, 0, -1 )
vals = [self.unpackage_val(x) for x in l]
self.log('-->',vals)
return vals
def remove(self,val):
self.log('<--',val)
if type(val)==list: return [self.remove(x) for x in val]
val_x = self.package_val(val)
res = self.redis.lrem(self.keyname, 0, val_x)
self.log('-->',res)
return res
if __name__=='__main__':
crypt = Crypt('testt')
from komrade import KomradeSymmetricKeyWithPassphrase
key = KomradeSymmetricKeyWithPassphrase()
crypt_list = CryptListRedis(
keyname='MyInbox2',
# crypt=crypt
)
print(crypt_list.values)
# print(crypt_list.remove('cool thing 0'))
# print(crypt_list.append('cool thing 1'))
print(crypt_list.append('#1 baby'))
print(crypt_list.append('cool thing 0'))
print(crypt_list.prepend('#0 baby'))
# print(crypt_list.remove('cool thing 0'))
print(crypt_list.values)

@ -233,13 +233,13 @@ KEYMAKER_DEFAULT_KEY_TYPES = {
def get_key_obj(keyname,data,key_types=KEYMAKER_DEFAULT_KEY_TYPES,getpass_func=None):
def get_key_obj(keyname,data,key_types=KEYMAKER_DEFAULT_KEY_TYPES,getpass_func=None,passphrase=None):
if keyname.endswith('_decr'):
# print('get_key_obj',keyname,data)#,key_types)
try:
data_s = data.decode()
if data_s in {KEY_TYPE_SYMMETRIC_WITH_PASSPHRASE,KomradeSymmetricKeyWithPassphrase.__name__}:
return KomradeSymmetricKeyWithPassphrase(getpass_func=getpass_func)
return KomradeSymmetricKeyWithPassphrase(getpass_func=getpass_func,passphrase=passphrase)
except UnicodeDecodeError:
return KomradeSymmetricKeyWithoutPassphrase(data)
@ -277,7 +277,7 @@ class Keymaker(Logger):
# logger.info('Keymaker booted with getpass_func',getpass_func)
# boot keychain
self._keychain = self.keychain()
# self._keychain = self.keychain()
def find_pubkey(self,name=None):
@ -318,7 +318,7 @@ class Keymaker(Logger):
keychain[keyname] = get_key_obj(keyname,keyval,getpass_func=self.getpass_func)
return keychain
def keychain(self,look_for=KEYMAKER_DEFAULT_ALL_KEY_NAMES):
def keychain(self,look_for=KEYMAKER_DEFAULT_ALL_KEY_NAMES,passphrase=None):
# load existing keychain
keys = self._keychain
@ -335,10 +335,10 @@ class Keymaker(Logger):
if keyname in keys and keys[keyname]: continue
key = self.crypt_keys.get(uri,prefix=f'/{keyname}/')
# print('found in crypt:',key,'for',keyname)
if key: keys[keyname]=get_key_obj(keyname,key,getpass_func=self.getpass_func)
if key: keys[keyname]=get_key_obj(keyname,key,getpass_func=self.getpass_func,passphrase=passphrase)
# try to assemble
keys = self.assemble(self.assemble(keys))
keys = self.assemble(self.assemble(keys,passphrase=passphrase),passphrase=passphrase)
#store to existing set
self._keychain = {**keys}
@ -497,7 +497,7 @@ class Keymaker(Logger):
return (uri_id,keys_saved_d,keychain)
def assemble(self,keychain,key_types=KEYMAKER_DEFAULT_KEY_TYPES,decrypt=True):
def assemble(self,keychain,key_types=KEYMAKER_DEFAULT_KEY_TYPES,decrypt=True,passphrase=None):
encr_keys = [k for k in keychain.keys() if k.endswith('_encr')]
for encr_key_name in encr_keys:
decr_key_name = encr_key_name[:-5] + '_decr'
@ -513,12 +513,12 @@ class Keymaker(Logger):
encr_key = keychain.get(encr_key_name)
# self.log(f'about to decrypt {encr_key} with {decr_key} and {decr_key.cell}')
unencr_key = decr_key.decrypt(encr_key.data)
keychain[unencr_key_name] = get_key_obj(unencr_key_name,unencr_key,getpass_func=self.getpass_func)
keychain[unencr_key_name] = get_key_obj(unencr_key_name,unencr_key,getpass_func=self.getpass_func,passphrase=passphrase)
else:
# unencr_key = keychain.get(unencr_key_name)
# self.log(f'about to encrypt {unencr_key} with {decr_key}')
encr_key = decr_key.encrypt(unencr_key.data)
keychain[encr_key_name] = get_key_obj(encr_key_name,encr_key,getpass_func=self.getpass_func)
keychain[encr_key_name] = get_key_obj(encr_key_name,encr_key,getpass_func=self.getpass_func,passphrase=passphrase)
except ThemisError as e:
#exit('Incorrect password.')
#self.log('error!!',e,decrypt,decr_key,encr_key,decr_key_name,encr_key_name)

@ -18,7 +18,7 @@ class KomradeX(Caller):
# logger.info('booting KomradeX with getpass_func:',getpass_func)
super().__init__(name=name, callbacks=callbacks, getpass_func=getpass_func)
self.log(f'Starting up with callbacks: {self._callbacks}')
self.boot(create=False)
# self.boot(create=False)
# special?
if self.name==WORLD_NAME:
if os.path.exists(PATH_SUPER_SECRET_OP_KEY):
@ -33,42 +33,60 @@ class KomradeX(Caller):
def boot(self,create=False,ping=False):
# Do I already have my keys?
# yes? -- login
return
keys = self.keychain()
# self.log(f'booting {self}!',dict_format(keys))
# # Do I already have my keys?
# # yes? -- login
if keys.get('pubkey') and keys.get('privkey'):
# self.log('already booted! @'+self.name)
return True
# 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
if self.exists_locally_as_account():
self.log(f'this account (@{self.name}) can be logged into')
return self.login()
# if self.exists_locally_as_account():
# self.log(f'this account (@{self.name}) can be logged into')
# return #self.login()
elif self.exists_locally_as_contact():
self.log(f'this account (@{self.name}) is a contact')
return #pass #???
# elif self.exists_locally_as_contact():
# self.log(f'this account (@{self.name}) is a contact')
# return #pass #???
elif ping and self.exists_on_server():
self.log(f'this account exists on server. introduce?')
return
# elif ping and self.exists_on_server():
# self.log(f'this account exists on server. introduce?')
# return
elif create:
self.log('account is free: register?')
return self.register()
# elif create:
# self.log('account is free: register?')
# return self.register()
def exists_locally(self):
return bool(self.pubkey)
pubkey=self.find_pubkey()
return bool(pubkey)
def exists_locally_as_contact(self):
return bool(self.pubkey) and not bool(self.privkey)
pubkey=self.find_pubkey()
if not pubkey: return False
uri=pubkey.data_b64
if self.crypt_keys.get(uri,prefix='/privkey_encr/'):
return False
return True
def exists_locally_as_account(self):
return bool(self.pubkey) and bool(self.privkey_encr)
#return bool(self.pubkey) and bool(self.privkey_encr)
pubkey=self.find_pubkey()
self.log('found pubkey:',pubkey)
if not pubkey: return False
uri=pubkey.data_b64
self.log('crypt????',self.crypt_keys.fn)
res = self.crypt_keys.get(uri,prefix='/privkey_encr/')
if res:
self.log('found privkey_encr:',res)
return True
return False
def exists_on_server(self):
answer = self.phone.ring_ring({
@ -81,10 +99,11 @@ class KomradeX(Caller):
## Talking with Operator
def ring_ring(self,msg,route=None,**y):
async def ring_ring(self,msg,route=None,**y):
logger.info('got here 2!')
if type(msg)==dict and not ROUTE_KEYNAME in msg:
msg[ROUTE_KEYNAME]=route
return super().ring_ring(msg,caller=self,**y)
return await super().ring_ring(msg,caller=self,**y)
@ -95,6 +114,9 @@ class KomradeX(Caller):
## (1) Logging in and registering ##
####################################
async def log_async(self,*x,**y):
return self.log(*x,**y)
def register(self, name = None, passphrase = None, is_group=None, show_intro=0,show_body=True,logfunc=None):
@ -579,7 +601,7 @@ class KomradeX(Caller):
)
## Getting updates
def get_updates(self,include_posts=True):
async def get_updates(self,include_posts=True):
# get any parameters we need
# post_ids_read = list(self.inbox_read_db.values)
if not self.pubkey:
@ -593,7 +615,7 @@ class KomradeX(Caller):
}
self.log('msg to op ->',msg_to_op)
res = self.ring_ring(
res = await self.ring_ring(
msg_to_op,
route='get_updates'
)

@ -28,15 +28,22 @@ class MazeWalker(Handler):
# print('! Found router:',record.msg % record.args)
# print(router.ip,walk)
# print()
f=None
if record.msg.startswith('Connecting to guard node'):
f = self._callbacks.get('torpy_guard_node_connect')
if f: f(router)
elif record.msg.startswith('Extending the circuit'):
f = self._callbacks.get('torpy_extend_circuit')
if f: f(router)
# import asyncio
# if f:
# asyncio.create_task(f(router))
#
if f:
# texec = ThreadExecutor()
# texec(f, router)
# f(router)
import asyncio
asyncio.run(f(router))
pass

@ -49,8 +49,8 @@ def Komrade(name=None,pubkey=None,*x,**y):
# print('found!',name,PHONEBOOK[name],PHONEBOOK[name].keychain())
PHONEBOOK[name] = kommie
if kommie.pubkey:
PHONEBOOK[kommie.pubkey.data_b64] = kommie
pubkey=kommie.find_pubkey(name)
if pubkey: PHONEBOOK[pubkey.data_b64] = kommie
return kommie
@ -102,10 +102,12 @@ class Operator(Keymaker):
getpass_func=getpass_func
)
# add to phonebook
if name: PHONEBOOK[name]=self
if self.pubkey: PHONEBOOK[self.pubkey.data_b64]=self
if name:
PHONEBOOK[name]=self
pubkey=self.find_pubkey(name)
if pubkey:
PHONEBOOK[pubkey.data_b64]=self
self._inbox_crypt=None
@ -249,7 +251,7 @@ class Operator(Keymaker):
return new_msg_obj
def ring_ring(self,msg,to_whom,get_resp_from=None,route=None,caller=None):
async def ring_ring(self,msg,to_whom,get_resp_from=None,route=None,caller=None):
# ring ring
from komrade.cli.artcode import ART_PHONE_SM1
import textwrap as tw
@ -277,8 +279,10 @@ class Operator(Keymaker):
# pass through the telephone wire by the get_resp_from function
if not get_resp_from: get_resp_from=to_whom.ring_ring
resp_msg_obj = get_resp_from(msg_obj.msg_d,caller=caller)
#self.log('resp_msg_obj <-',resp_msg_obj)
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()

@ -38,7 +38,7 @@ class TheTelephone(Operator):
return OPERATOR_API_URL
def send_and_receive(self,msg_d,**y):
async def send_and_receive(self,msg_d,**y):
# self.log('send and receive got incoming msg:',msg_d)
# assert that people can speak only with operator in their first enclosed message!
@ -66,7 +66,15 @@ class TheTelephone(Operator):
URL = self.api_url + msg_b64_str_esc + '/'
self.log("DIALING THE OPERATOR:",URL)
phonecall=self.komrade_request(URL)
# phonecall=await self.komrade_request_async(URL)
# import asyncio
# loop = asyncio.get_event_loop()
texec = ThreadExecutor()
# phonecall=self.komrade_request(URL)
phonecall = await texec(self.komrade_request, URL)
if phonecall.status_code!=200:
self.log('!! error in request',phonecall.status_code,phonecall.text)
return
@ -95,8 +103,8 @@ class TheTelephone(Operator):
# return self.pronto_pronto(resp_msg_obj)
def ring_ring(self,msg,**y):
return super().ring_ring(
async def ring_ring(self,msg,**y):
return await super().ring_ring(
msg,
to_whom=self.op,
get_resp_from=self.send_and_receive,
@ -109,6 +117,13 @@ class TheTelephone(Operator):
return self.tor_request(url)
return requests.get(url,timeout=600)
async def komrade_request_async(self,url,allow_clearnet=ALLOW_CLEARNET):
import requests_async as requests
if '.onion' in url or not allow_clearnet:
return await self.tor_request_async(url)
return await requests.get(url,timeout=600)
def tor_request(self,url):
return self.tor_request_in_python(url)
# return tor_request_in_proxy(url)
@ -119,21 +134,21 @@ class TheTelephone(Operator):
def tor_request_in_proxy(self,url):
with self.get_tor_proxy_session() as s:
return s.get(url,timeout=60)
return s.get(url,timeout=600)
async def tor_request_in_python_async(self,url):
import requests_async as requests
tor = TorClient(
callbacks=self._callbacks
)
import requests_async
tor = TorClient()
with tor.get_guard() as guard:
adapter = TorHttpAdapter(guard, 3, retries=RETRIES)
async with requests.Session() as s:
async with requests_async.Session() as s:
s.headers.update({'User-Agent': 'Mozilla/5.0'})
s.mount('http://', adapter)
s.mount('https://', adapter)
return await s.get(url, timeout=60)
r = s.get(url, timeout=600)
self.log('<-- r',r)
return r
def tor_request_in_python(self,url):
@ -145,7 +160,7 @@ class TheTelephone(Operator):
s.headers.update({'User-Agent': 'Mozilla/5.0'})
s.mount('http://', adapter)
s.mount('https://', adapter)
r = s.get(url, timeout=60)
r = s.get(url, timeout=600)
return r
def get_tor_proxy_session(self):

@ -15,6 +15,7 @@ PATH_USER_HOME = os.path.join(os.path.expanduser('~'))
PATH_KOMRADE = os.path.abspath(os.path.join(os.path.expanduser('~'),'komrade','data'))
PATH_KOMRADE_KEYS = os.path.join(PATH_KOMRADE,'.keys')
PATH_KOMRADE_DATA = os.path.join(PATH_KOMRADE,'.data')
PATH_KOMRADE_LIB = os.path.abspath(os.path.join(os.path.expanduser('~'),'komrade','lib'))
PATH_CRYPT_OP_KEYS = os.path.join(PATH_KOMRADE_KEYS,'.op.db.keys.crypt')
PATH_CRYPT_OP_DATA = os.path.join(PATH_KOMRADE_DATA,'.op.db.data.crypt')
@ -49,12 +50,24 @@ BSEP3=b'##########'
OPERATOR_NAME = 'Operator'
TELEPHONE_NAME = 'Telephone'
WORLD_NAME = 'komrades'
PATH_APP = os.path.abspath(os.path.dirname(__file__))
PATH_REPO = os.path.abspath(
os.path.join(
os.path.dirname(__file__),
'..'
)
)
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_REPO = PATH_APP = os.path.abspath(os.path.dirname(__file__))
# PATH_APP = os.path.join(PATH_REPO,'komrade')
# PATH_BUILTIN_KEYCHAINS_ENCR = os.path.join(PATH_APP,'.builtin.keychains.encr')
PATH_BUILTIN_KEYCHAIN = os.path.join(PATH_APP,'.builtin.keys')
PATH_OMEGA_KEY = os.path.join(PATH_APP,'.omega.key')
# PATH_BUILTIN_KEYCHAINS_DECR = os.path.join(PATH_APP,'.builtin.keychains.decr')
PATH_GUI = os.path.join(PATH_APP, )
# key names
@ -187,3 +200,199 @@ if not 'KOMRADE_USE_TOR' in os.environ or not os.environ['KOMRADE_USE_TOR']:
KOMRADE_USE_TOR = os.environ['KOMRADE_USE_TOR'] = '1'
if not 'KOMRADE_USE_CLEARNET' in os.environ or not os.environ['KOMRADE_USE_CLEARNET']:
KOMRADE_USE_CLEARNET = os.environ['KOMRADE_USE_CLEARNET'] = '0'
FONT_PATH = os.path.join(PATH_GUI_ASSETS,'font.otf')
#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)]
DEFAULT_URI='/login/'
import random,platform
HORIZONTAL = True # random.choice([True,True,True,False])
FACTOR=1
WINDOW_SIZE = (1136*FACTOR,640*FACTOR) if HORIZONTAL else (640*FACTOR,1136*FACTOR)
PLAYING_CARDS = (2.5,3.5)
ASPECT_RATIO = PLAYING_CARDS[0]/PLAYING_CARDS[1]
ASPECT_RATIO = 1/ASPECT_RATIO
HEIGHT = 850
if platform.platform().startswith('Linux'):
HEIGHT *= 1.25
WINDOW_SIZE=int(HEIGHT),int(HEIGHT * ASPECT_RATIO)
BG_IMG='assets/bg-brown.png'
grass=(201,203,163)
russiangreen = (109,140,96)
huntergreen = (67,92,61)
kombugreen = (49,67,45)
pinetreegreen = (29,40,27)
junglegreen = (15, 21, 14)
browncoffee=(77, 42, 34)
rootbeer=(38, 7, 1)
blackbean=(61, 12, 2)
burntumber=(132, 55, 34)
brownsugar=(175, 110, 81)
antiquebrass= (198, 144, 118)
royalbrown=(94, 55, 46)
bole=(113, 65, 55)
liver= (110, 56, 31)
bistre=(58, 33, 14)
bistre2=(43, 21, 7)
skin1=(89, 47, 42)
skin2=(80, 51, 53)
skin3=(40, 24, 26)
grullo=177, 158, 141
smokyblack=33, 14, 0
liverchestnut=148, 120, 96
ashgray=196, 199, 188
livchestnut2=156, 106, 73
beaver=165, 134, 110
rawumber=120, 95, 74
persianred=202,52,51
vermillion=126,25,27
indianred=205,92,92
barnred=124,10,2
maroon=128,0,0
bloodred=98, 23, 8
rust=188, 57, 8
darksienna=34, 9, 1
yellowcrayola=246, 170, 28
darkred=148, 27, 12
rosewood=94, 11, 21
redviolet=144, 50, 61
bone=217, 202, 179
bronze=188, 128, 52
shadow=140, 122, 107
orangered=194, 3, 3
dutchwhite=229,219,181
# black=(0,0,0)
black=15, 15, 15 #5, 8, 13
eerieblack=23, 22, 20
bistre=58, 38, 24
tuscanred=117, 64, 67
grullo2=154, 136, 115
blackolive=55, 66, 61
dogreen=103, 116, 35
sage=187, 193, 145
alabaster2 = 241, 236, 226
coyotebrown = 138, 93, 61
vandykebrown = 90, 62, 41
darksienna2=55, 6, 23
xiketic=3, 7, 30
rossacorsa=208, 0, 0
raisinblack=38, 34, 34
coffee2=67, 58, 58
rufusred=171, 4, 4
darksienna3=56, 22, 13
black2=0, 20, 39
xanadu=112, 141, 129
jasmine=244, 213, 141
ioe=191, 6, 3
dred=141, 8, 1
caputmort1=74, 36, 25
# SCHEME = 'lgreen'
# SCHEME = 'bronze'
SCHEME = 'dark'
# light green theme?
if SCHEME=='lgreen':
COLOR_TOOLBAR= huntergreen #bone #smokyblack #5,5,5 #russiangreen #pinetreegreen #kombugreen #(12,5,5) #russiangreen
COLOR_BG = grass # russiangreen #(0,73,54)
COLOR_LOGO = coyotebrown # grass#russiangreen #(0,0,0) #(0,0,0) #(151,177,140) #(132,162,118) #(109,140,106)
COLOR_TEXT = black #(255,245,200) #(0,0,0,1) #(241,233,203) #COLOR_ICON #(207,219,204) #(239,235,206) # (194,211,187) # (171,189,163) # (222,224,198) # COLOR_LOGO #(223, 223, 212)
COLOR_CARD = bone #(67,92,61) #(12,9,10)
COLOR_CARD_BORDER = COLOR_CARD
COLOR_ICON=COLOR_LOGO
elif SCHEME=='bronze':
COLOR_TOOLBAR= junglegreen
COLOR_BG = bronze
COLOR_LOGO = rufusred #yellowcrayola #0,0,0
COLOR_TEXT = black
COLOR_CARD = bone
COLOR_CARD_BORDER = COLOR_CARD
COLOR_ICON=COLOR_LOGO
else:
# COLOR_TOOLBAR= black
# COLOR_TOOLBAR=bronze
# COLOR_LOGO = black #bronze #0,0,0
# COLOR_BG = black
COLOR_BG=bistre
COLOR_TOOLBAR=black
COLOR_LOGO=bronze
COLOR_TEXT = black
COLOR_CARD = bone
COLOR_CARD_BORDER = COLOR_CARD
COLOR_ICON=COLOR_LOGO
COLOR_ACCENT = huntergreen
COLOR_INACTIVE = COLOR_CARD
COLOR_ACTIVE = russiangreen
ALL_COLORS = list({v for (k,v) in globals().items() if type(v)==tuple and len(v)==3})

@ -451,4 +451,38 @@ def multiline_input(msg=None):
break
txt="\n".join(contents) if contents else contents
return txt
return txt
class ThreadExecutor:
"""In most cases, you can just use the 'execute' instance as a
function, i.e. y = await execute(f, a, b, k=c) => run f(a, b, k=c) in
the executor, assign result to y. The defaults can be changed, though,
with your own instantiation of Executor, i.e. execute =
Executor(nthreads=4)"""
def __init__(self, loop=None, nthreads=1):
import asyncio
from concurrent.futures import ThreadPoolExecutor
if not loop: loop=asyncio.get_event_loop()
self._ex = ThreadPoolExecutor(nthreads)
self._loop = loop
def __call__(self, f, *args, **kw):
from functools import partial
return self._loop.run_in_executor(self._ex, partial(f, *args, **kw))
# execute = Executor()
# ...
# def cpu_bound_operation(t, alpha=30):
# sleep(t)
# return 20*alpha
# async def main():
# y = await execute(cpu_bound_operation, 5, alpha=-2)
# loop.run_until_complete(main())

@ -69,3 +69,4 @@ utm==0.6.0
watchdog==0.10.3
Werkzeug==1.0.1
wrapt==1.12.1
hirlite

@ -89,6 +89,7 @@ echo '
cd $path_komrade
path_conda="$path_komrade/lib/miniconda3"
# ### Detect if python 3.7?
# pyv="$(python3 -c 'import sys; print(sys.version_info[0:2])')"
# if [ ! "$pyv" = "(3, 7)" ]
@ -105,18 +106,24 @@ esac
if [ "$machine" = "Linux" ]
then
curl https://repo.anaconda.com/miniconda/Miniconda3-py37_4.8.3-Linux-x86_64.sh -o miniconda.sh
chmod +x miniconda.sh
./miniconda.sh -b -f -p "$path_komrade/lib/miniconda3"
rm miniconda.sh
if [ ! -f "miniconda.sh" ]
then
curl https://repo.anaconda.com/miniconda/Miniconda3-py37_4.8.3-Linux-x86_64.sh -o miniconda.sh
chmod +x miniconda.sh
fi
./miniconda.sh -b -f -p "$path_conda"
#rm miniconda.sh
fi
if [ "$machine" = "Mac" ]
then
curl https://repo.anaconda.com/miniconda/Miniconda3-py37_4.8.3-MacOSX-x86_64.sh -o miniconda.sh
chmod +x miniconda.sh
./miniconda.sh -b -f -p "$path_komrade/lib/miniconda3"
rm miniconda.sh
if [ ! -f "miniconda.sh" ]
then
curl https://repo.anaconda.com/miniconda/Miniconda3-py37_4.8.3-MacOSX-x86_64.sh -o miniconda.sh
chmod +x miniconda.sh
fi
./miniconda.sh -b -f -p "$path_conda"
# rm miniconda.sh
fi
if [ "$machine" = "Cygwin" ]
@ -129,27 +136,41 @@ then
curl https://repo.anaconda.com/miniconda/Miniconda3-py37_4.8.3-Windows-x86.exe -o miniconda.exe
fi
./miniconda.exe -b -f -p "$path_komrade/lib/miniconda3"
rm miniconda.exe
./miniconda.exe -b -f -p "$path_conda"
# rm miniconda.exe
fi
pythonexec="$path_komrade/lib/miniconda3/bin/python"
# activate conda
export PATH="$path_conda/bin:$PATH"
source "$path_conda/etc/profile.d/conda.sh"
condaexec="conda"
pythonexec="python"
echo '
4) creating virtual environment...
'
path_venv="$path_repo/venv"
# cd $path_komrade
cd $path_repo
echo "Now using python 1: `which python`"
$condaexec create -y -p "$path_venv" python=3.7 cartopy pip virtualenv
cd $path_komrade
$pythonexec -m pip install virtualenv
$pythonexec -m virtualenv venv
. venv/bin/activate
echo "Now using python: `which python`"
#$condaexec activate "$path_venv"
echo "Now using python 2: `which python`"
# $pythonexec -m pip install virtualenv
# $pythonexec -m virtualenv venv
# . venv/bin/activate
echo "Now using python 3: `which python`"
cd $path_repo
python -m pip install -r requirements.txt
echo '

Loading…
Cancel
Save