FLO-appStore/main.py
2019-02-23 23:45:54 +05:30

342 lines
12 KiB
Python
Executable File

#!/usr/bin/env python3
from tkinter import *
from tkinter import messagebox
import subprocess
import os
import sys
import webbrowser
import json
import math
import socket
import requests
import hashlib
JsonAddresses = ["FT9qkvuWXWBDRhHd42tDr5nMYFSx7bEhV7","FBcRbCxwChjTdgVewGMPBDDEFXzPcc7GAH","FC6CRkRCeJEKEGF2r1SFppPD5DXfVe1zWq"]
def searchDict(dicArr,key,val):
for i in range(len(dicArr)):
if(dicArr[i][key]==val):
return i
return -1
def findHash(data):
result = hashlib.sha1(data.encode())
return str(result.hexdigest())
def isConnected():
try:
socket.create_connection(("www.github.com", 80))
return True
except:
messagebox.showerror('FLOappStore', "Unable to Connect to GitHub!\nPlease check Internet connectivity and firewall!")
return False
def readUnitFromBlockchain(txid):
rawtx = subprocess.check_output(["flo-cli", "getrawtransaction", str(txid)])
rawtx = str(rawtx)
rawtx = rawtx[2:-3]
tx = subprocess.check_output(["flo-cli", "decoderawtransaction", str(rawtx)])
content = json.loads(tx)
text = content['floData']
return str(text)
def Dappend(Dapps,app):
i = searchDict(Dapps,'id',app['id'])
#print(str(i))
if (i!=-1):
del(Dapps[i])
#print(app.keys())
if ('remove' not in app.keys()):
Dapps = Dapps + [app]
return Dapps
def verifyHash(localHash,txid):
content = readUnitFromBlockchain(txid)
#print(content)
try:
if(json.loads(content)['hash'] == localHash):
return True
else:
return False
except:
return False
def getJsonData(Dapps, lastTx,JsonAddress):
try:
r = requests.get("https://www.florincoin.info/ext/getaddress/"+JsonAddress)
data = json.loads(r.content)
except:
isConnected()
return
#print(Dapps)
localHash = findHash(str(Dapps))
try:
if(lastTx == -1 or not verifyHash(localHash,data['last_txs'][lastTx]['addresses'])):
lastTx = 0
else:
lastTx = lastTx+1
except:
lastTx = 0
#print(lastTx)
for i in range(lastTx,len(data['last_txs'])):
#print(i)
if(data['last_txs'][i]['type']=='vin'):
content = readUnitFromBlockchain(data['last_txs'][i]['addresses'])
#print(content)
try:
app = json.loads(content)
except Exception as e:
#print(e)
continue
#print(app)
try:
if 'Dapp' in app.keys():
Dapps = Dappend(Dapps,app['Dapp'])
except:
continue
#print(Dapps)
{'Dapps':apps ,'lastTx':lastTx}
returndata = {}
returndata['Dapps'] = Dapps
returndata['lastTx'] = len(data['last_txs'])-1
return (returndata)
class FLOappStore:
def __init__(self, root):
self.root = root
self.maxRow=5
self.maxCol=2
def start(self):
self.MainFrame = Frame(self.root)
self.MainFrame.pack()
WelcomeLabel = Label(self.MainFrame,text="FLO AppStore",font=("Arial", 20))
WelcomeLabel.grid(row=1,column = 1,columnspan=2)
self.searchBox=Entry(self.MainFrame)
self.searchBox.grid(row=2,column=1,sticky="E")
self.searchButton=Button(self.MainFrame,text="Search",command = self.searchApps)
self.searchButton.grid(row=2,column=2,sticky="W")
self.searchApps()
def clearSearch(self):
self.searchBox.delete(0, 'end')
self.searchApps()
def searchApps(self):
try:
self.clearSearchButton.destroy()
except:
None
self.searchResult=[]
searchText=self.searchBox.get()
if(searchText != ""):
self.clearSearchButton=Button(self.MainFrame,text="Clear Search",command = self.clearSearch)
self.clearSearchButton.grid(row=2,column=2,sticky="N")
for app in apps:
if (searchText.lower() in app["name"].lower()):
self.searchResult = self.searchResult + [app]
self.totalPage = math.ceil(len(self.searchResult)/(self.maxRow*self.maxCol))
self.listApps(1)
def listApps(self,pageNum):
try:
self.listFrame.destroy()
except:
None
self.listFrame = Frame(self.MainFrame)
if not len(self.searchResult):
noResultLabel = Label(self.listFrame,text="No Apps found!")
noResultLabel.grid()
self.listFrame.grid(column=1,columnspan=2)
return
if pageNum<1:
pageNum=self.totalPage
elif pageNum>self.totalPage:
pageNum=1
self.icon=[]
self.appButton=[]
Xrow=1
Xcol=1
startIndex=(pageNum-1)*(self.maxRow*self.maxCol)
for app in self.searchResult[startIndex:]:
try:
img=PhotoImage(file=app["icon"])
except:
img=PhotoImage(file='Icon/noimage.png')
self.icon= self.icon+[img]
self.appButton = self.appButton + [Button(self.listFrame,text=app["name"],image = self.icon[-1],compound="left",width="500",height="50",command=lambda app=app:self.execute(app))]
self.appButton[-1].grid(row = Xrow,column = Xcol)
Xcol=Xcol+1
if (Xcol>self.maxCol):
Xcol=1
Xrow=Xrow+1
if (Xrow>self.maxRow):
break
prevButton = Button(self.listFrame,text="Prev",command=lambda :self.listApps(pageNum-1))
nextButton = Button(self.listFrame,text="Next",command=lambda :self.listApps(pageNum+1))
pageLabel = Label(self.listFrame,text=f"{pageNum}/{self.totalPage}")
prevButton.grid(row=self.maxRow+1,column=1,columnspan=self.maxCol,sticky="W")
nextButton.grid(row=self.maxRow+1,column=1,columnspan=self.maxCol,sticky="NE")
pageLabel.grid(row=self.maxRow+1,column=1,columnspan=self.maxCol,sticky="N")
self.listFrame.grid(column=1,columnspan=2)
def execute(self,app):
#print(app["name"])
isConnected()
self.appWin = Toplevel()
self.appWin.title(app["name"])
self.appWin.geometry("500x400")
self.appWin.resizable(0,0)
try:
description = app["description"]
except:
description = '*NIL*'
Label1 = Label(self.appWin, text="Description")
Label1.pack()
GTextFrame = Frame(self.appWin)
GScroll = Scrollbar(GTextFrame)
GScroll.pack(side=RIGHT, fill=Y)
self.GLMsg = Text(GTextFrame,height=10,width=50,yscrollcommand=GScroll.set)
self.GLMsg.insert(END, description)
self.GLMsg.config(state='disabled')
self.GLMsg.pack(side = LEFT)
GTextFrame.pack()
GScroll.config(command=self.GLMsg.yview)
if(app["type"] == "Gui" or app["type"] == "Cmdline"):
if(os.path.isdir(app["location"]) and subprocess.Popen("git config --get remote.origin.url",cwd=app["location"],stdout=subprocess.PIPE,shell=True).communicate()[0].decode("utf-8").strip()==app["github"]):
openButton = Button(self.appWin,text="Open App",command=lambda :self.openApp(app))
openButton.pack()
if(subprocess.Popen("git diff --raw",cwd=app["location"],stdout=subprocess.PIPE,shell=True).communicate()[0].decode("utf-8")!=""):
updateButton = Button(self.appWin,text="Update App",command=lambda :self.updateApp(app))
updateButton.pack()
removeButton = Button(self.appWin,text="Remove App",command=lambda :self.removeApp(app))
removeButton.pack()
else:
downloadButton = Button(self.appWin,text="Download App",command=lambda :self.downloadApp(app))
downloadButton.pack()
elif(app["type"] == "Webapp"):
openButton = Button(self.appWin,text="Open Browser",command=lambda :self.openBrowserApp(app))
openButton.pack()
self.appWin.mainloop()
def downloadApp(self,app):
self.appWin.destroy()
subprocess.Popen(['rm', '-rf', app['location']])
if(not isConnected()):
return
subprocess.Popen("gnome-terminal -- git clone %s"%(app["github"]),cwd="apps/",shell=True)
messagebox.showinfo(app['name'], f"Downloading {app['name']}...\n Please Wait until the downloader closes")
def removeApp(self,app):
self.appWin.destroy()
subprocess.Popen(['rm', '-rf', app['location']])
messagebox.showinfo(app['name'], f"Removed {app['name']}...")
def updateApp(self,app):
self.appWin.destroy()
if(not isConnected()):
return
subprocess.Popen("gnome-terminal -- git pull --all",cwd=app['location'],shell=True)
subprocess.Popen("gnome-terminal -- git reset --hard HEAD ",cwd=app['location'],shell=True)
messagebox.showinfo(app['name'], f"Updating {app['name']}...\n Please Wait until the updater closes")
def openApp(self,app):
self.appWin.destroy()
if(app["type"] == "Gui"):
subprocess.Popen(app["exec"], cwd=app["location"])
elif(app["type"] == "Cmdline"):
subprocess.Popen("gnome-terminal --command 'bash -c %s;bash'"%(app["exec"]),cwd=app["location"],stdout=subprocess.PIPE,shell=True)
def openBrowserApp(self,app):
self.appWin.destroy()
webbrowser.open(app["url"],new=1)
def refreshAppData():
global apps
apps = []
print("Refreshing App Details")
try:
with open('Apps.json','r') as F:
data=json.loads(F.read())
flag = True
except:
flag = False
data = {}
for addr in JsonAddresses:
try:
appdata = data[addr]['Dapps']
#print(appdata)
lastTx = data[addr]['lastTx']
except:
appdata = []
lastTx = -1
data[addr] = getJsonData(appdata,lastTx,addr)
#print(data[addr])
apps = apps + data[addr]['Dapps']
with open('Apps.json','w+') as F:
#print(data)
data = json.dumps(data)
F.write(data)
print("Loaded App Details")
def Credits():
print("Credits")
creditsWin = Toplevel()
creditsWin.title('Credits')
infoLabel = Label(creditsWin,text="FLO AppStore",font=("Arial", 16))
infoLabel.pack()
vLabel = Label(creditsWin,text="version 1.0",font=("Arial", 8))
vLabel.pack()
creditLabel1 = Label(creditsWin,text="\n--Created by--",font=("Arial", 10))
creditLabel1.pack()
creditLabel2 = Label(creditsWin,text="Ranchi Mall Internship Blockchain Contract",font=("Arial", 12))
creditLabel2.pack()
internLabel = Label(creditsWin,text="Interns : Sai Raj, Kaushal",font=("Arial", 8))
internLabel.pack()
forLabel1 = Label(creditsWin,text="\n--For--",font=("Arial", 10))
forLabel1.pack()
forLabel2 = Label(creditsWin,text="Ranchi Mall FLO Blockchain Contract",font=("Arial", 12))
forLabel2.pack()
creditsWin.mainloop()
refreshAppData()
root = Tk()
root.title("FLOappStore")
root.geometry("1100x500")
root.resizable(0,0)
menubar = Menu(root)
appmenu = Menu(menubar, tearoff=0)
appmenu.add_command(label="Refresh", command=refreshAppData)
appmenu.add_separator()
appmenu.add_command(label="Exit", command=root.quit)
menubar.add_cascade(label="App", menu=appmenu)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="ReadMe", command=lambda :webbrowser.open("README.md"))
helpmenu.add_command(label="GitHub", command=lambda :webbrowser.open("https://github.com/ranchimall/FLO-appStore",new=1))
helpmenu.add_separator()
helpmenu.add_command(label="Credits", command=Credits)
menubar.add_cascade(label="Help", menu=helpmenu)
root.config(menu=menubar)
gui = FLOappStore(root)
gui.start()
root.mainloop()