def __init__(self): self.init_home_dir() self.api = "https://andrefreitas.pt/budibox/api/" self.login = LoginBox() self.watcher = Watcher(self.budibox_home)
class ClientDaemon: def __init__(self): self.init_home_dir() self.api = "https://andrefreitas.pt/budibox/api/" self.login = LoginBox() self.watcher = Watcher(self.budibox_home) def init_home_dir(self): # Searchs for user home folder and creates budibox folder self.budibox_home = expanduser("~") + "/budibox" self.home = expanduser("~") self.budibox_home = self.budibox_home.decode(system_enconding) # Creates budibox folder if not os.path.exists(self.budibox_home): os.makedirs(self.budibox_home) def client_start(self): self.login.start() self.computerId = self.get_computer_id() watcher_thread = Thread(target=self.listen_watcher, args=()) requests_thread = Thread(target=self.listen_requests, args=()) keep_alive = Thread(target=self.keep_alive, args=()) sync = Thread(target=self.sync, args=()) # Start threads watcher_thread.start() requests_thread.start() keep_alive.start() sync.start() # Join threads watcher_thread.join() requests_thread.join() keep_alive.join() sync.join() def get_computer_id(self): url = self.api + "computers/getComputerId.php" values = {"apikey": "12", "user": login_box.client.get_email(), "computer": get_computer_name()} response = json_request(url, values) print_message("Getting the computer ID") if response["result"] == "ok": return response["computerId"] def sync(self): while True: url = self.api + "files/getUserFiles.php" values = {"apikey": "12", "user": login_box.client.get_email()} response = json_request(url, values) if response["result"] != "ok": print_message("Error trying to get user files of " + login_box.client.get_email()) else: print_message("Total files: " + str(len(response["files"]))) self.restore_file(response["files"]) time.sleep(sync_files_interval) def restore_file(self, files): list_dir = os.listdir(self.budibox_home) global restore_requests for file in files: file_path = file["path"] if os.path.isfile(self.budibox_home + file_path): if file["status"] == "deleted": os.remove(self.budibox_home + file_path) break timestamp = int(file["date_modified"]["sec"]) datetime_request = datetime.fromtimestamp(timestamp) datetime_local_file = datetime.fromtimestamp(os.path.getmtime(self.budibox_home + file_path)) difference_times = ( time.mktime(datetime_request.timetuple()) - time.mktime(datetime_local_file.timetuple()) - 3600 ) if difference_times > 0: if not (file_path in restore_requests): print_message("More recent " + file_path) url = self.api + "files/restoreFile.php" values = {"apikey": "12", "computerId": self.computerId, "modification": file["modification"]} response = json_request(url, values) if response["result"] == "ok": print_message("Sent request of restore file of " + file_path) restore_requests[file_path] = False else: print_message("Error sending request of restore file of " + file_path) else: print "older or equal" else: if not (file_path in restore_requests) and file["status"] != "deleted": url = self.api + "files/restoreFile.php" values = {"apikey": "12", "computerId": self.computerId, "modification": file["modification"]} response = json_request(url, values) restore_requests[file_path] = False if response["result"] == "ok": print_message("Sent request of restore file of " + file_path) else: print_message("Error sending request of restore file of " + file_path) def keep_alive(self): while True: url = self.api + "computers/keepAlive.php" values = {"apikey": "12", "computerId": self.computerId} response = json_request(url, values) if response["result"] != "ok": print_message("Error sending message of keepAlive of computerId " + self.computerId) time.sleep(10) def listen_watcher(self): self.watcher.start(login_box.client, self.computerId) def listen_requests(self): while True: url = self.api + "requests/getComputerRequests.php" values = {"apikey": "12", "computerId": self.computerId} response = json_request(url, values) if response["result"] == "ok": total_requests = len(response["requests"]) print_message("Requests: " + str(total_requests)) if total_requests > 0: self.handle_request(response["requests"]) time.sleep(listen_requests_interval) def handle_request(self, requests): for request in requests: if request["action"] == "storeChunk": self.store_chunk(request["chunkNumber"], request["modification"], request["fileId"]) if request["action"] == "deleteFile": self.delete_chunks(request["modification"]) if request["action"] == "giveChunk": if os.path.exists( self.budibox_home + "/chunks/" + request["modification"] + "_" + str(request["chunkNumber"]) + ".chunk" ): self.send_chunk_to_restore(request["modification"], request["chunkNumber"], request["owner"]) if request["action"] == "recoverChunk": self.store_temp_chunk(request["modification"], request["number"], request["path"]) def store_temp_chunk(self, modification, number, path): temp_dir = self.home + "/chunks_restore/temp/" if not os.path.exists(temp_dir): os.makedirs(temp_dir) # Creates chunk temp_dir = temp_dir.decode(system_enconding) chunk = open(temp_dir + modification + "_" + str(number) + ".chunk", "w") # Gets chunk body url = self.api + "chunks/getRecover.php" values = {"apikey": "12", "owner": self.computerId, "number": str(number), "modification": modification} response = json_request(url, values) if response["result"] == "ok": chunk_body = response["chunk"] chunk.write(chunk_body) chunk.close() print_message("Chunk of " + modification + " and number " + str(number) + " writed!") else: chunk.close() print_message("Error getting chunk of " + modification + " and number " + str(number) + " writed!") # Delete chunk recover url = self.api + "chunks/deleteChunkRecover.php" values = {"apikey": "12", "owner": self.computerId, "modification": modification, "number": str(number)} response = json_request(url, values) if response["result"] == "ok": print_message("Deleted chunk recover !") else: print_message("Error deleting chunk recover!") return # Confirm chunk recover url = self.api + "requests/confirmRecoverChunk.php" values = { "apikey": "12", "computerId": self.computerId, "modification": modification, "chunkNumber": str(number), } response = json_request(url, values) if response["result"] == "ok": print_message("Confirmed chunk recover !") else: print_message("Error confirming chunk recover!") return # Checks if received all chunks url = self.api + "files/restoreFileIsDone.php" values = {"apikey": "12", "computerId": self.computerId, "modification": modification} response = json_request(url, values) if response["result"] == "ok": if response["isDone"] == True: print_message("Restore file " + path + " is done!") f = File(self.budibox_home + path, login_box.client, modification) f.restore_file(temp_dir, self.budibox_home + path) global restore_requests del restore_requests[path] print "Feito" def send_chunk_to_restore(self, modification, number, owner): path = self.budibox_home + "/chunks/" + modification + "_" + str(number) + ".chunk" chunk = open(path, "rb") chunk_body = chunk.read() url = self.api + "chunks/giveForRestore.php" values = { "apikey": "12", "modification": modification, "number": str(number), "body": chunk_body, "owner": owner["$id"], } response = json_post_request(url, values) if response["result"] == "ok": print_message("Sent chunk for restore of " + path) else: print_message("Error sending chunk for restore of " + path) def delete_chunks(self, modification): list_dir = os.listdir(self.budibox_home + "/chunks/") for file in list_dir: if file.startswith(modification): f = open(self.budibox_home + "/chunks/" + file, "rb") file_size = len(f.read()) f.close() os.remove(self.budibox_home + "/chunks/" + file) url = self.api + "users/incOfferUsage.php" values = {"apikey": "12", "user": login_box.client.get_email(), "value": str(-file_size)} response = json_request(url, values) if response["result"] == "ok": print_message("Decremented offer_usage in " + str(file_size)) else: print_message("Error decrementing offer_usage in " + str(file_size)) url = self.api + "requests/confirmFileDelete.php" values = {"apikey": "12", "computerId": self.computerId, "modification": modification} response = json_request(url, values) if response["result"] == "ok": print_message("Sent confirm delete message of modification: " + modification) else: print_message("Error confirm delete message of modification: " + modification) def store_chunk(self, chunkNumber, modification, fileId): # Gets Information about chunk to Store url = self.api + "chunks/get.php" values = {"apikey": "12", "fileId": fileId["$id"], "modification": modification, "number": str(chunkNumber)} response = json_request(url, values) if response["result"] == "ok": chunk_body = response["chunk"] else: print_message( "Error trying to get chunk body of fileID " + fileId["$id"] + "and chunkNumber " + str(chunkNumber) ) return False print_message( "Processing request, getting chunk body of " + fileId["$id"] + " and chunkNumber " + str(chunkNumber) ) if not os.path.exists(self.budibox_home + "/chunks/"): os.makedirs(self.budibox_home + "/chunks/") chunk_file = open(self.budibox_home + "/chunks/" + modification + "_" + str(chunkNumber) + ".chunk", "wb") chunk_file.write(chunk_body) chunk_file.close() # Sends confirmStorage message url = self.api + "chunks/confirmStorage.php" values = { "apikey": "12", "fileId": fileId["$id"], "computerId": self.computerId, "number": str(chunkNumber), "modification": modification, } response = json_request(url, values) if response["result"] == "ok": print_message( "Sent confirmation message: fileId " + fileId["$id"] + " and chunkNumber " + str(chunkNumber) + " and computerId " + self.computerId ) # Adds space of the offer_used url = self.api + "users/incOfferUsage.php" values = {"apikey": "12", "user": login_box.client.get_email(), "value": str(len(chunk_body))} response_space = json_request(url, values) if response_space["result"] == "ok": print_message("Increment offer usage successfully with " + str(len(chunk_body))) return True else: print_message("Error in incrementing offer usage with " + str(len(chunk_body))) return False else: print_message( "Error trying to send confirm message: fileId " + fileId["$id"] + " and chunkNumber " + str(chunkNumber) + " and computerId " + self.computerId ) return False