def handle_ignore(self): """Dummy files are in the format: .{name} Do not have to get the actual filename """ alert = QtWidgets.QMessageBox() alert.setWindowTitle("Ignore selected files") alert.setIcon(QtWidgets.QMessageBox.Warning) alert.setText( "You are about to ignore some files. This will generate hidden files in your download directory" ) alert.setDetailedText( "This will generate hidden files in the download directory so that ignored " "files will not appear the menu in the future.\n" "To undo, you need to enable show hidden files in your file " "explorer and remove the files you want to download. E.g. if you want to download Tut_4, look for .Tut_4 and remove it" ) alert.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) retval = alert.exec_() if retval == QtWidgets.QMessageBox.Ok: path_and_nodes = self.get_paths_and_selected_nodes() for path, node in path_and_nodes: node_data = node.data(0, Qt.UserRole) create_dummy_file(path, sanitise_filename(node_data["name"])) self.downloadProgressText.setText( "Ignored {} files and recorded lectures".format( len(path_and_nodes))) if retval == QtWidgets.QMessageBox.Cancel: pass
def download_from_nodes(progress_callback): """Return tuple (files downloaded, files skipped, download_links) """ numDownloaded, numSkipped = 0, 0 data_deltas = [] for idx, (path, node) in enumerate(paths_and_nodes): node_data = node.data(0, Qt.UserRole) node_type = node_data["type"] save_flag = False # load the download link and file name from API if needed if node_data.get("download_link") is None: save_flag = True try: if node_type == "file": download_link = get_file_download_link( self.BbRouter, node_data["predownload_link"]) filename = get_filename_from_url(download_link) elif node_type == "recorded_lecture": download_link = get_recorded_lecture_download_link( self.BbRouter, node_data["predownload_link"]) filename = node_data["name"] + ".mp4" except Exception as e: trace = traceback.format_exc() progress_callback.emit((idx + 1, node_data['name'], False, None, None, trace)) data_deltas.append(None) continue else: download_link = node_data.get("download_link") filename = node_data.get("filename") full_file_path = os.path.join(path, sanitise_filename(filename)) if os.path.exists(full_file_path): numSkipped += 1 progress_callback.emit( (idx + 1, filename, False, None, None, None)) else: numDownloaded += 1 download( self.BbRouter, download_link, full_file_path, lambda bytes_downloaded, total_content_length: progress_callback.emit( (idx + 1, filename, True, bytes_downloaded, total_content_length, None)), ) data_deltas.append((download_link, filename) if save_flag else None) return (numDownloaded, numSkipped, data_deltas)
def traverse(data, parent, path): """recursively traverse NTU Learn data and render all file/video nodes, if the file/video already exists, set the node as hidden """ node = QtWidgets.QTreeWidgetItem(parent) # save relevant data fields into node.data node_data = {"name": data["name"], "type": data["type"]} data_type = data["type"] if data_type == "folder": node.setIcon(0, self.folderIcon) node.setFlags(node.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable) next_path = os.path.join(path, sanitise_filename(data["name"]), "") for child in data["children"]: traverse(child, node, next_path) elif data_type == "file" or data_type == "recorded_lecture": # add file/video attributes node_data["predownload_link"] = data["predownload_link"] node_data["download_link"] = data.get("download_link") node_data["filename"] = data.get("filename") # ignore file if dummy file is present is_dummy_file_present = dummy_file_exists( path, sanitise_filename(node_data["name"])) is_file_present = node_data["filename"] and os.path.exists( os.path.join(path, sanitise_filename( node_data["filename"]))) if is_dummy_file_present or is_file_present: node.setHidden(True) node.setIcon( 0, self.fileIcon if data_type == "file" else self.videoIcon) node.setFlags(node.flags() | Qt.ItemIsUserCheckable) else: raise Exception("unknown type", data_type) node.setText(0, data["name"]) node.setCheckState(0, Qt.Unchecked) node.setData(0, Qt.UserRole, node_data)
def traverse(node, path): if node.checkState(0) == Qt.Unchecked or node.isHidden(): return node_data = node.data(0, Qt.UserRole) node_type = node_data["type"] if node_type == "file" or node_type == "recorded_lecture": result.append((path, node)) else: next_path = os.path.join(path, sanitise_filename(node_data["name"])) for index in range(node.childCount()): traverse(node.child(index), next_path)
def test_sanitise_filename(self): name = 'Week 1: Tutorial (1/2).mp4' self.assertEqual('Week 1 Tutorial (1-2).mp4', sanitise_filename(name))
def download_files( BbRouter: str, obj: Dict, download_path: str, ignore_files: bool = False, ignore_recorded_lectures: bool = False, to_prompt: bool = False, ): if obj["type"] == "folder": download_path = os.path.join(download_path, sanitise_filename(obj["name"]), "") for c in obj["children"]: download_files( BbRouter, c, download_path, ignore_files, ignore_recorded_lectures, to_prompt, ) elif obj["type"] == "file": if ignore_files: return download_link = get_file_download_link(BbRouter, obj["predownload_link"]) filename = get_filename_from_url(download_link) if filename is None: print("Unable to get filename from: {}".format(download_link)) return full_file_path = os.path.join(download_path, sanitise_filename(filename)) # although we get the filename from the download link, some have the same name as in the # download link so we can potentially save a network call here if os.path.exists(full_file_path): return print("- {}".format(full_file_path)) download(BbRouter, download_link, full_file_path) return elif obj["type"] == "recorded_lecture": if ignore_recorded_lectures: return # can infer video name without expensive call to get download link video_name = sanitise_filename(obj["name"] + ".mp4") full_file_path = os.path.join(download_path, video_name) if os.path.exists(full_file_path) or dummy_file_exists( download_path, video_name): return download_link = get_recorded_lecture_download_link( BbRouter, obj["predownload_link"]) video_size = get_video_download_size(download_link) to_download = True if to_prompt: to_download = (query_yes_no( "Download {}, ({})? ['Enter' for Y]".format( video_name, video_size), default="yes") == "yes") if to_download: print("- {} ({})".format(full_file_path, video_size or "Unknown")) download(BbRouter, download_link, full_file_path) else: dummy_file_path = create_dummy_file(download_path, video_name) print("Created dummy file:", dummy_file_path) return