You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Comrad/client/main.py

328 lines
10 KiB
Python

## CONFIG
# change this to your external ip address for your server
#(needs to be external to allow tor routing)
SERVER_ADDR = '128.232.229.63:5555'
DEFAULT_SCREEN='profile'
HORIZONTAL = False
WINDOW_SIZE = (1136,640) if HORIZONTAL else (640,1136)
# imports
4 years ago
from kivy.uix.screenmanager import Screen,ScreenManager
from kivymd.app import MDApp
4 years ago
from kivymd.uix.button import MDFillRoundFlatButton, MDIconButton
from kivymd.uix.toolbar import MDToolbar
from kivymd.uix.screen import MDScreen
4 years ago
from kivy.lang import Builder
4 years ago
from kivy.uix.boxlayout import BoxLayout
from kivymd.theming import ThemeManager
from kivy.properties import ObjectProperty,ListProperty
import time,os
4 years ago
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
4 years ago
from kivymd.uix.list import OneLineListItem
from kivymd.uix.card import MDCard, MDSeparator
from kivymd.uix.boxlayout import MDBoxLayout
4 years ago
from kivy.uix.gridlayout import GridLayout
from kivy.metrics import dp
from kivy.properties import NumericProperty
4 years ago
from kivymd.uix.list import * #MDList, ILeftBody, IRightBody, ThreeLineAvatarListItem, TwoLineAvatarListItem, BaseListItem, ImageLeftWidget
from kivy.uix.image import Image, AsyncImage
4 years ago
import requests,json
from kivy.storage.jsonstore import JsonStore
from kivy.core.window import Window
4 years ago
from kivy.core.text import LabelBase
4 years ago
import shutil
Window.size = WINDOW_SIZE
4 years ago
def log(*args):
4 years ago
with open('log.txt','a+') as of:
of.write(' '.join([str(x) for x in args])+'\n')
4 years ago
class MyLayout(MDBoxLayout):
4 years ago
scr_mngr = ObjectProperty(None)
post_id = ObjectProperty()
4 years ago
4 years ago
def change_screen(self, screen, *args):
self.scr_mngr.current = screen
def view_post(self,post_id):
self.post_id=post_id
self.change_screen('view')
4 years ago
4 years ago
class MyBoxLayout(MDBoxLayout): pass
class MyLabel(MDLabel): pass
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
#### LOGIN
4 years ago
4 years ago
4 years ago
def get_tor_proxy_session():
session = requests.session()
# Tor uses the 9050 port as the default socks port
session.proxies = {'http': 'socks5://127.0.0.1:9050',
'https': 'socks5://127.0.0.1:9050'}
return session
def get_async_tor_proxy_session():
from requests_futures.sessions import FuturesSession
session = FuturesSession()
# Tor uses the 9050 port as the default socks port
session.proxies = {'http': 'socks5://127.0.0.1:9050',
'https': 'socks5://127.0.0.1:9050'}
return session
4 years ago
def get_tor_python_session():
from torpy.http.requests import TorRequests
with TorRequests() as tor_requests:
with tor_requests.get_session() as s:
return s
4 years ago
class MainApp(MDApp):
title = 'Komrade'
4 years ago
#api = 'http://localhost:5555/api'
api = 'http://%s/api' % SERVER_ADDR
4 years ago
#api = 'http://komrades.net:5555/api'
logged_in=False
store = JsonStore('komrade.json')
login_expiry = 60 * 60 * 24 * 7 # once a week
#login_expiry = 5 # 5 seconds
4 years ago
4 years ago
def get_session(self):
# return get_async_tor_proxy_session()
4 years ago
return get_tor_proxy_session()
#return get_tor_python_session()
4 years ago
def get_username(self):
if hasattr(self,'username'): return self.username
self.load_store()
if hasattr(self,'username'): return self.username
return ''
4 years ago
def build(self):
4 years ago
self.username=''
4 years ago
# bind
4 years ago
global app,root
4 years ago
app = self
4 years ago
#self.username = self.store.get('userd').get('username')
self.load_store()
4 years ago
self.root = root = Builder.load_file('root.kv')
4 years ago
# edit logo
logo=root.ids.toolbar.ids.label_title
logo.font_name='assets/Strengthen.ttf'
logo.font_size='58dp'
logo.pos_hint={'center_y':0.43}
# icons
icons=root.ids.toolbar.ids.right_actions.children
for icon in icons:
#log(dir(icon))
#icon.icon='android' #user_font_size='200sp'
icon.font_size='58dp'
icon.user_font_size='58dp'
icon.width='58dp'
icon.size_hint=(None,None)
icon.height='58dp'
if not self.is_logged_in():
self.root.change_screen('login')
4 years ago
log(self.username)
else:
# self.root.post_id=190
self.root.change_screen(DEFAULT_SCREEN)
4 years ago
return self.root
4 years ago
4 years ago
def load_store(self):
if not self.store.exists('user'): return
userd=self.store.get('user')
if not userd: userd={}
self.logged_in_when = userd.get('logged_in_when')
self.username = userd.get('username','')
def is_logged_in(self,just_check_timestamp=True, use_caching=True):
if self.logged_in: return True
4 years ago
if not use_caching: return False
###
if not self.store.exists('user'): return False
4 years ago
userd=self.store.get('user')
if not userd: userd={}
if userd.get('logged_in'):
un=userd.get('username')
timestamp=userd.get('logged_in_when')
# just a time check
if timestamp and just_check_timestamp:
if time.time() - timestamp < self.login_expiry:
self.logged_in=True
#self.username=un
return True
return False
4 years ago
def save_login(self,un):
self.logged_in=True
4 years ago
self.username=un
# self.store.put('username',un)
self.store.put('user',username=un,logged_in=True,logged_in_when=time.time())
4 years ago
self.root.change_screen('feed')
4 years ago
4 years ago
def login(self,un=None,pw=None):
4 years ago
url = self.api+'/login'
4 years ago
4 years ago
with self.get_session() as sess:
#res = requests.post(url, json={'name':un, 'passkey':pw})
res = sess.post(url, json={'name':un, 'passkey':pw})
log(res.text)
4 years ago
if res.status_code==200:
4 years ago
data=res.json()
self.save_login(un)
return True
4 years ago
else:
4 years ago
# self.root.ids.login_status.text=res.text
return False
4 years ago
def register(self,un,pw):
4 years ago
url = self.api+'/register'
with self.get_session() as sess:
#res = requests.post(url, json={'name':un, 'passkey':pw})
res = sess.post(url, json={'name':un, 'passkey':pw})
if res.status_code==200:
4 years ago
self.save_login(un)
4 years ago
else:
pass
#self.root.ids.login_status.text=res.text
4 years ago
def upload(self,orig_img_src):
url_upload=self.api+'/upload'
filename=orig_img_src[0] if orig_img_src and os.path.exists(orig_img_src[0]) else ''
if not filename: return
server_filename=''
media_uid=None
4 years ago
with self.get_session() as sess:
with sess.post(url_upload,files={'file':open(filename,'rb')}) as r1:
if r1.status_code==200:
rdata1 = r1.json()
server_filename = rdata1.get('filename','')
media_uid=rdata1.get('media_uid')
if server_filename:
# pre-cache
cache_filename = os.path.join('cache','img',server_filename)
cache_filedir = os.path.dirname(cache_filename)
if not os.path.exists(cache_filedir): os.makedirs(cache_filedir)
shutil.copyfile(filename,cache_filename)
return {'cache_filename':cache_filename, 'media_uid':media_uid, 'server_filename':server_filename}
def post(self, content='', media_uid=None):
timestamp=time.time()
jsond = {'content':str(content),'media_uid':media_uid,
'username':self.username, 'timestamp':timestamp}
4 years ago
url_post = self.api+'/post'
with self.get_session() as sess:
4 years ago
# post
4 years ago
with sess.post(url_post, json=jsond) as r2:
log('got back from post: ' + r2.text)
rdata2 = r2.json()
post_id = rdata2.get('post_id',None)
if post_id:
4 years ago
# pre-cache
cache_dir = os.path.join('cache','json',post_id[:3])
cache_fnfn = os.path.join(cache_dir,post_id[3:]+'.json')
if not os.path.exists(cache_dir): os.makedirs(cache_dir)
with open(cache_fnfn,'w') as of:
4 years ago
json.dump(jsond, of)
#self.root.view_post(post_id)
self.root.change_screen('feed')
return {'post_id':post_id}
4 years ago
4 years ago
def get_post(self,post_id):
4 years ago
# get json from cache?
ofn_json = os.path.join('cache','json',str(post_id)+'.json')
if os.path.exists(ofn_json):
with open(ofn_json) as f:
jsond = json.load(f)
else:
with self.get_session() as sess:
with sess.get(self.api+'/post/'+str(post_id)) as r:
jsond = r.json()
# cache it!
with open(ofn_json,'w') as of:
json.dump(jsond, of)
return jsond
def get_posts(self):
with self.get_session() as sess:
with sess.get(self.api+'/posts') as r:
log(r.text)
jsond=r.json()
return jsond['posts']
return []
def get_posts_async(self):
result=[]
with self.get_session() as sess:
futures = [sess.get(self.api+'/posts')]
for future in as_completed(futures):
log('second?')
r=future.result()
log(r.text)
jsond=r.json()
result=jsond['posts']
log('first?')
return result
def get_image(self, img_src):
4 years ago
# is there an image?
if not img_src: return
# is it cached?
ofn_image = os.path.join('cache','img',img_src)
if not os.path.exists(ofn_image):
# create dir?
ofn_image_dir = os.path.split(ofn_image)[0]
if not os.path.exists(ofn_image_dir): os.makedirs(ofn_image_dir)
log('getting image!')
with self.get_session() as sess:
with sess.get(self.api+'/download/'+img_src,stream=True) as r:
with open(ofn_image,'wb') as of:
shutil.copyfileobj(r.raw, of)
return ofn_image
4 years ago
4 years ago
4 years ago
if __name__ == '__main__':
App = MainApp()
App.run()