munyal-client/munyal/client.py

240 lines
7.5 KiB
Python
Raw Normal View History

2019-07-28 16:18:49 +00:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
2020-12-08 20:45:42 +00:00
import base64
2019-07-28 16:18:49 +00:00
import json
import os
import pathlib
import sys
import shutil
2020-12-19 22:48:55 +00:00
import websocket
2019-07-28 16:18:49 +00:00
from copy import deepcopy
2019-11-30 22:49:14 +00:00
from datetime import datetime
2019-07-28 16:18:49 +00:00
from random import randint
from shutil import rmtree
from threading import Thread
from time import sleep
2020-12-09 21:29:45 +00:00
from uuid import uuid4
2019-07-28 16:18:49 +00:00
from PIL import Image, ImageTk
from requests import post
2020-12-08 20:45:42 +00:00
from pystray import Icon, Menu
from pystray import MenuItem as Item
from websocket import WebSocket
2020-12-19 22:48:55 +00:00
from munyal.compare_json import compare_json
from munyal.config import get_config
from munyal.config import get_last_history
from munyal.config import set_last_history
from munyal.dir_to_json import get_json
from munyal.misc import check_network
from munyal.misc import path_join
2020-12-08 20:45:42 +00:00
try:
import thread
except ImportError:
import _thread as thread
2019-07-28 16:18:49 +00:00
2020-12-17 21:54:44 +00:00
2019-11-30 22:49:14 +00:00
_online_icon = Image.open("img/icons/online.png")
_offline_icon = Image.open("img/icons/offline.png")
_standby_icon = Image.open("img/icons/standby.png")
2019-11-30 22:49:14 +00:00
2020-12-08 20:45:42 +00:00
if not int(os.getenv("VERBOSE", 1)):
def X(*args, **kwargs):
pass
print = X
2019-07-28 16:18:49 +00:00
2019-12-03 09:24:36 +00:00
class MunyalClient(Icon):
2019-08-18 01:09:33 +00:00
def __init__(self):
super(MunyalClient, self).__init__("Munyal")
2020-12-08 20:45:42 +00:00
self.__ws_break = False
self.ws = None
2019-11-30 22:49:14 +00:00
self.icon = _standby_icon
2019-08-18 01:09:33 +00:00
self.config = get_config()
self.stack = []
2020-12-09 02:47:09 +00:00
self.ignored = []
2019-07-28 16:18:49 +00:00
2019-08-18 01:09:33 +00:00
def is_online(self):
2020-12-08 20:45:42 +00:00
# if not self.ws_online:
# self.icon = _standby_icon
# return False
if self.__ws_break:
self.icon = _standby_icon
return False
2019-08-18 01:09:33 +00:00
ping = check_network("http://google.com", 443)
if ping:
2019-11-30 22:49:14 +00:00
self.icon = _online_icon
2019-07-28 16:18:49 +00:00
else:
2019-11-30 22:49:14 +00:00
self.icon = _offline_icon
2020-12-08 20:45:42 +00:00
print(f"La PC está {'on' if bool(ping) else 'off'}line")
return ping
def __ws_message(self, ws, message):
print(message)
def __ws_error(self, ws, error):
print("Error: ", error)
def __ws_open(self):
print("WebSocket abierto")
thread.start_new_thread(self.listener, ())
2019-08-18 01:09:33 +00:00
def start(self):
2020-12-08 20:45:42 +00:00
websocket.enableTrace(True)
# ws.on_open = self.listener
2019-11-30 22:49:14 +00:00
thread_uploader = Thread(target=self.uploader,
name="uploader",
daemon=True)
thread_downloader = Thread(target=self.downloader,
name="downloader",
daemon=True)
2020-12-08 20:45:42 +00:00
# thread_listener = Thread(target=self.listener,
# name="listener",
# daemon=True)
2019-08-18 01:09:33 +00:00
thread_uploader.start()
# thread_downloader.start()
2020-12-08 20:45:42 +00:00
# thread_listener.start()
2019-12-03 09:24:36 +00:00
self.menu = Menu(Item("Exit", lambda *args: sys.exit(0)))
self.run(self.__run)
2019-08-18 01:09:33 +00:00
def __run(self, icon):
icon.visible = True
2020-12-08 20:45:42 +00:00
while True:
print("Conectando al websocket")
2020-12-17 21:54:44 +00:00
websocket.enableTrace(False)
2020-12-08 20:45:42 +00:00
ws = websocket.WebSocketApp(
f"ws://{self.config['login']['user']}.loca.lt",
# "ws://127.0.0.1:12345",
2020-12-09 02:47:09 +00:00
on_message=self.__download,
2020-12-08 20:45:42 +00:00
on_error=print,
on_close=lambda soc: self.__ws_close(ws))
ws.on_open = lambda soc: self.listener(soc)
ws.run_forever()
sleep(1)
2019-08-18 01:09:33 +00:00
2020-12-08 20:45:42 +00:00
def __ws_close(self, ws):
print("WebSocket cerrado")
self.__ws_break = True
self.icon = _standby_icon
2020-12-08 20:45:42 +00:00
def listener(self, ws):
self.ws = ws
def wrapper(*args):
2020-12-09 02:47:09 +00:00
folder = self.config["folder"]
uuid = self.config["uuid"]
2020-12-08 20:45:42 +00:00
while True:
if self.stack:
data = self.stack[0]
2020-12-08 20:45:42 +00:00
try:
2020-12-09 02:47:09 +00:00
data["uuid"] = uuid
if data["name"] in self.ignored:
self.ignored.remove(data["name"])
self.stack.pop(0)
continue
2020-12-08 20:45:42 +00:00
if data["is_file"] and data["action"] == "add":
2020-12-09 03:37:51 +00:00
full_path = path_join(folder, data["name"])
2020-12-08 20:45:42 +00:00
data["file"] = base64.b85encode(
open(full_path, "rb").read()).decode("ascii")
self.ws.send(json.dumps(data))
self.stack.pop(0)
except Exception as e:
if data["is_file"] and data["action"] == "add":
path = path_join(folder, data["name"])
if not os.path.exists(path):
self.stack.pop(0)
print("the file does not exists anymore, skiped")
else:
print(e)
print("Error uploading file, trying again")
2020-12-08 20:45:42 +00:00
if not self.is_online() or self.__ws_break:
self.__ws_break = False
self.ws = None
return
sleep(1)
thread.start_new_thread(wrapper, ())
2019-08-18 01:09:33 +00:00
def uploader(self):
print("Uploader")
folder = self.config["folder"]
last = get_last_history()
if last is None:
last = get_json(folder)
2019-08-18 01:09:33 +00:00
while True:
sleep(1)
actual = get_json(folder)
_actual = deepcopy(actual)
delete, add = compare_json(last, actual)
if delete:
print("Cosas eliminadas:")
print(len(delete))
2020-12-08 20:45:42 +00:00
for f in delete:
f["action"] = "delete"
self.stack.extend(delete)
if add:
print("Cosas agregadas:")
print(len(add))
2020-12-08 20:45:42 +00:00
for f in add:
f["action"] = "add"
self.stack.extend(add)
last = _actual
if delete or add:
set_last_history(last)
2019-07-28 16:18:49 +00:00
2019-08-18 01:09:33 +00:00
def __upload(self, path):
pass
2019-07-28 16:18:49 +00:00
2020-12-09 02:47:09 +00:00
def downloader(self, data):
name = data["name"]
self.ignored.append(name)
2020-12-09 03:37:51 +00:00
full_path = path_join(self.config["folder"], name)
2020-12-09 02:47:09 +00:00
if data["is_file"]:
if data["action"] == "add":
directory = os.path.split(full_path)[0]
if not os.path.exists(directory):
os.makedirs(directory, exist_ok=True)
2020-12-09 21:29:45 +00:00
directory, _ = os.path.split(full_path)
temp_name = str(uuid4()) + ".tmp"
temp_dir = path_join(directory, temp_name)
with open(temp_dir, "wb") as f:
2020-12-09 02:47:09 +00:00
f.write(base64.b85decode(data["file"].encode("ascii")))
2020-12-09 21:29:45 +00:00
os.rename(temp_dir, full_path)
2020-12-09 02:47:09 +00:00
else:
while True:
try:
os.remove(full_path)
break
except:
print("Maybe the file is open, please close first")
sleep(5)
2020-12-09 02:47:09 +00:00
else:
if data["action"] == "add":
os.mkdir(full_path)
else:
shutil.rmtree(full_path)
def __download(self, message):
try:
data = json.loads(message)
except Exception:
return
if data["uuid"] != self.config["uuid"]:
2020-12-09 02:50:57 +00:00
self.downloader(data)
2019-07-28 16:18:49 +00:00
if __name__ == '__main__':
2019-08-18 01:09:33 +00:00
try:
client = MunyalClient()
client.start()
sys.exit(0)
2020-12-09 03:37:51 +00:00
except BaseException as e:
print(e)
2019-08-18 01:09:33 +00:00
sys.exit(1)