def get_dir_list(self, folder_id=-1) -> FolderList: """获取子文件夹列表""" folder_list = FolderList() para = { 'item': 'files', 'action': 'index', 'folder_node': 1, 'folder_id': folder_id } html = self._get(self._mydisk_url, params=para) if not html: return folder_list info = re.findall( r' (.+?)</a> .+"folk(\d+)"(.*?)>.+#BBBBBB">\[?(.*?)\.*\]?</font>', html.text) for folder_name, fid, pwd_flag, desc in info: folder_list.append( Folder( id=int(fid), name=folder_name.replace('&', '&'), # 修复网页中的 & 为 & has_pwd=True if pwd_flag else False, # 有密码时 pwd_flag 值为 style="display:initial" desc=desc # 文件夹描述信息 )) return folder_list
def get_rec_dir_list(self) -> FolderList: """获取回收站文件夹列表""" # 回收站中文件(夹)名只能显示前 17 个中文字符或者 34 个英文字符,如果这些字符相同,则在文件(夹)名后添加 (序号) ,以便区分 html = self._get(self._mydisk_url, params={ 'item': 'recycle', 'action': 'files' }) if not html: return FolderList() dirs = re.findall( r'folder_id=(\d+).+?> (.+?)\.{0,3}</a>.*\n+.*<td.+?>(.+?)</td>.*\n.*<td.+?>(.+?)</td>', html.text) all_dir_list = FolderList() # 文件夹信息列表 dir_name_list = [] # 文件夹名列表d counter = 1 # 重复计数器 for fid, name, size, time in dirs: if name in dir_name_list: # 文件夹名前 17 个中文或 34 个英文重复 counter += 1 name = f'{name}({counter})' else: counter = 1 dir_name_list.append(name) all_dir_list.append(RecFolder(name, int(fid), size, time, None)) return all_dir_list
def init_variables(self): self._disk = LanZouCloud() self._config_file = "./config.pkl" self._folder_list = {} self._file_list = {} self._path_list = FolderList() self._path_list_old = FolderList() self._locs = {} self._parent_id = -1 # --> .. self._work_name = "" # share disk rec, not use now self._work_id = -1 # disk folder id self._old_work_id = self._work_id # 用于上传完成后判断是否需要更新disk界面 self.load_settings()
def __init__(self): self._prompt = '> ' self._disk = LanZouCloud() self._dir_list = FolderList() self._file_list = FileList() self._path_list = FolderList() self._parent_id = -1 self._parent_name = '' self._work_name = '' self._work_id = -1 self._last_work_id = -1 self._reader_mode = config.reader_mode self._disk.set_max_size(config.max_size) self._is_login = False
def __init__(self): self._prompt = '> ' self._disk = LanZouCloud() self._task_mgr = global_task_mgr self._dir_list = FolderList() self._file_list = FileList() self._path_list = FolderList() self._parent_id = -1 self._parent_name = '' self._work_name = '' self._work_id = -1 self._last_work_id = -1 self._reader_mode = config.reader_mode self._disk.set_max_size(config.max_size) self._disk.set_captcha_handler(captcha_handler)
def get_move_paths(self) -> List[FolderList]: """获取所有文件夹的绝对路径(耗时长)""" result = [] root = FolderList() root.append(FolderId('LanZouCloud', -1)) result.append(root) resp = self._post(self._doupload_url, data={"task": 19, "file_id": -1}) if not resp or resp.json()['zt'] != 1: # 获取失败或者网络异常 return result ex = ThreadPoolExecutor() # 线程数 min(32, os.cpu_count() + 4) id_list = [int(folder['folder_id']) for folder in resp.json()['info']] task_list = [ex.submit(self.get_full_path, fid) for fid in id_list] for task in as_completed(task_list): result.append(task.result()) return sorted(result)
def get_rec_all(self): """获取整理后回收站的所有信息""" root_files = self.get_rec_file_list() # 回收站根目录文件列表 folder_list = FolderList() # 保存整理后的文件夹列表 for folder in self.get_rec_dir_list(): # 遍历所有子文件夹 this_folder = RecFolder(folder.name, folder.id, folder.size, folder.time, FileList()) for file in self.get_rec_file_list(folder.id): # 文件夹内的文件属性: name,id,type,size if root_files.find_by_id(file.id): # 根目录存在同名文件 file_time = root_files.pop_by_id(file.id).time # 从根目录删除, time 信息用来补充文件夹中的文件 file = file._replace(time=file_time) # 不能直接更新 namedtuple, 需要 _replace this_folder.files.append(file) else: # 根目录没有同名文件(用户手动删了),文件还在文件夹中,只是根目录不显示,time 信息无法补全了 file = file._replace(time=folder.time) # 那就设置时间为文件夹的创建时间 this_folder.files.append(file) folder_list.append(this_folder) return root_files, folder_list
def __init__(self): self._prompt = '> ' self._disk = LanZouCloud() # self._disk.ignore_limits() self._task_mgr = global_task_mgr self._dir_list = FolderList() self._file_list = FileList() self._path_list = FolderList() self._parent_id = -1 self._parent_name = '' self._work_name = '' self._work_id = -1 self._last_work_id = -1 self._reader_mode = config.reader_mode self._default_dir_pwd = config.default_dir_pwd self._disk.set_max_size(config.max_size) self._disk.set_upload_delay(config.upload_delay)
def get_full_path(self, folder_id=-1) -> FolderList: """获取文件夹完整路径""" path_list = FolderList() path_list.append(FolderId('LanZouCloud', -1)) html = self._get(self._mydisk_url, params={'item': 'files', 'action': 'index', 'folder_id': folder_id}) if not html: return path_list html = remove_notes(html.text) path = re.findall(r'» .+?folder_id=(\d+)">.+? (.+?)</a>', html) for fid, name in path: path_list.append(FolderId(name, int(fid))) # 获取当前文件夹名称 if folder_id != -1: current_folder = re.search(r'align="(top|absmiddle)" /> (.+?)\s<(span|font)', html).group(2).replace( '&', '&') path_list.append(FolderId(current_folder, folder_id)) return path_list
def logout(self): """注销""" clear_screen() self._prompt = '> ' self._disk.logout() self._file_list.clear() self._dir_list.clear() self._path_list = FolderList() self._parent_id = -1 self._work_id = -1 self._last_work_id = -1 self._parent_name = '' self._work_name = '' config.cookie = None
def get_move_folders(self) -> FolderList: """获取全部文件夹 id-name 列表,用于移动文件至新的文件夹""" # 这里 file_id 可以为任意值,不会对结果产生影响 result = FolderList() result.append(FolderId(name='LanZouCloud', id=-1)) resp = self._post(self._doupload_url, data={"task": 19, "file_id": -1}) if not resp or resp.json()['zt'] != 1: # 获取失败或者网络异常 return result for folder in resp.json()['info']: folder_id, folder_name = int(folder['folder_id']), folder['folder_name'] result.append(FolderId(folder_name, folder_id)) return result
class Commander: """蓝奏网盘命令行""" def __init__(self): self._prompt = '> ' self._disk = LanZouCloud() self._dir_list = FolderList() self._file_list = FileList() self._path_list = FolderList() self._parent_id = -1 self._parent_name = '' self._work_name = '' self._work_id = -1 self._last_work_id = -1 self._reader_mode = config.reader_mode self._disk.set_max_size(config.max_size) self._is_login = False @staticmethod def clear(): clear_screen() @staticmethod def help(): print_help() @staticmethod def update(): check_update() def rmode(self): """适用于屏幕阅读器用户的显示方式""" choice = input("以适宜屏幕阅读器的方式显示(y): ") if choice and choice.lower() == 'y': config.reader_mode = True self._reader_mode = True info("已启用 Reader Mode") else: config.reader_mode = False self._reader_mode = False info("已关闭 Reader Mode") def cdrec(self): """进入回收站模式""" rec = Recovery(self._disk) rec.run() self.refresh() def refresh(self, dir_id=None): """刷新当前文件夹和路径信息""" dir_id = self._work_id if dir_id is None else dir_id self._file_list = self._disk.get_file_list(dir_id) self._dir_list = self._disk.get_dir_list(dir_id) self._path_list = self._disk.get_full_path(dir_id) self._prompt = '/'.join(self._path_list.all_name) + ' > ' self._last_work_id = self._work_id self._work_name = self._path_list[-1].name self._work_id = self._path_list[-1].id if dir_id != -1: # 如果存在上级路径 self._parent_name = self._path_list[-2].name self._parent_id = self._path_list[-2].id def login(self, username=None, password=None): """登录网盘""" if not config.cookie or self._disk.login_by_cookie( config.cookie) != LanZouCloud.SUCCESS: if username is None: username = input('输入用户名:') if password is None: password = getpass('输入密码:') code = self._disk.login(username, password) if code == LanZouCloud.NETWORK_ERROR: error("登录失败,网络连接异常") return self elif code == LanZouCloud.FAILED: error('登录失败,用户名或密码错误 :(') return self # 登录成功保存用户 cookie config.cookie = self._disk.get_cookie() self.refresh() self._is_login = True print("auth success!\n") return self def clogin(self): """使用 cookie 登录""" open_new_tab('https://pc.woozooo.com/') info("请设置 Cookie 内容:") ylogin = input("ylogin="******"phpdisk_info=") if not ylogin or not disk_info: error("请输入正确的 Cookie 信息") return None cookie = {"ylogin": str(ylogin), "phpdisk_info": disk_info} if self._disk.login_by_cookie(cookie) == LanZouCloud.SUCCESS: config.cookie = cookie self.refresh() self._is_login = True else: error("登录失败,请检查 Cookie 是否正确") def logout(self): """注销""" clear_screen() self._prompt = '> ' self._disk.logout() self._file_list.clear() self._dir_list.clear() self._path_list = FolderList() self._parent_id = -1 self._work_id = -1 self._last_work_id = -1 self._parent_name = '' self._work_name = '' self_is_login = False config.cookie = None def ls(self): """列出文件(夹)""" if self._reader_mode: # 方便屏幕阅读器阅读 for folder in self._dir_list: print(f"{folder.name}/ {folder.desc}") for file in self._file_list: print(f"{file.name} 大小:{file.size} 上传时间:{file.time}") else: # 普通用户显示方式 for folder in self._dir_list: pwd_str = '✦' if folder.has_pwd else '✧' print("#{0:<12}{1:<4}{2}{3}/".format( folder.id, pwd_str, text_align(folder.desc, 24), folder.name)) for file in self._file_list: pwd_str = '✦' if file.has_pwd else '✧' print("#{0:<12}{1:<4}{2:<14}{3:<10}{4}".format( file.id, pwd_str, file.time, file.size, file.name)) def cd(self, dir_name): """切换工作目录""" if not dir_name: info('cd .. 返回上级路径, cd - 返回上次路径, cd / 返回根目录') elif dir_name == '..': self.refresh(self._parent_id) elif dir_name == '/': self.refresh(-1) elif dir_name == '-': self.refresh(self._last_work_id) elif dir_name == '.': pass elif folder := self._dir_list.find_by_name(dir_name): self.refresh(folder.id) else:
class Commander: """蓝奏网盘命令行""" def __init__(self): self._prompt = '> ' self._disk = LanZouCloud() # self._disk.ignore_limits() self._task_mgr = global_task_mgr self._dir_list = FolderList() self._file_list = FileList() self._path_list = FolderList() self._parent_id = -1 self._parent_name = '' self._work_name = '' self._work_id = -1 self._last_work_id = -1 self._reader_mode = config.reader_mode self._default_dir_pwd = config.default_dir_pwd self._disk.set_max_size(config.max_size) self._disk.set_upload_delay(config.upload_delay) @staticmethod def clear(): clear_screen() @staticmethod def help(): print_help() @staticmethod def update(): check_update() def bye(self): if self._task_mgr.has_alive_task(): info(f"有任务在后台运行, 退出请直接关闭窗口") else: exit_cmd(0) def rmode(self): """适用于屏幕阅读器用户的显示方式""" choice = input("以适宜屏幕阅读器的方式显示(y): ") if choice and choice.lower() == 'y': config.reader_mode = True self._reader_mode = True info("已启用 Reader Mode") else: config.reader_mode = False self._reader_mode = False info("已关闭 Reader Mode") def cdrec(self): """进入回收站模式""" rec = Recovery(self._disk) rec.run() self.refresh() def xghost(self): """扫描并删除幽灵文件夹""" choice = input("需要清理幽灵文件夹吗(y): ") if choice and choice.lower() == 'y': self._disk.clean_ghost_folders() info("清理已完成") else: info("清理操作已取消") def refresh(self, dir_id=None): """刷新当前文件夹和路径信息""" dir_id = self._work_id if dir_id is None else dir_id self._file_list = self._disk.get_file_list(dir_id) self._dir_list = self._disk.get_dir_list(dir_id) self._path_list = self._disk.get_full_path(dir_id) self._prompt = '/'.join(self._path_list.all_name) + ' > ' self._last_work_id = self._work_id self._work_name = self._path_list[-1].name self._work_id = self._path_list[-1].id if dir_id != -1: # 如果存在上级路径 self._parent_name = self._path_list[-2].name self._parent_id = self._path_list[-2].id def login(self): """使用 cookie 登录""" if not config.cookie or self._disk.login_by_cookie( config.cookie) != LanZouCloud.SUCCESS: open_new_tab('https://pc.woozooo.com/') info("请设置 Cookie 内容:") ylogin = input("ylogin="******"phpdisk_info=") if not ylogin or not disk_info: error("请输入正确的 Cookie 信息") return None cookie = {"ylogin": str(ylogin), "phpdisk_info": disk_info} if self._disk.login_by_cookie(cookie) == LanZouCloud.SUCCESS: config.cookie = cookie else: error("登录失败,请检查 Cookie 是否正确") self.refresh() def logout(self): """注销""" clear_screen() self._prompt = '> ' self._disk.logout() self._file_list.clear() self._dir_list.clear() self._path_list = FolderList() self._parent_id = -1 self._work_id = -1 self._last_work_id = -1 self._parent_name = '' self._work_name = '' config.cookie = None def ls(self): """列出文件(夹)""" if self._reader_mode: # 方便屏幕阅读器阅读 for folder in self._dir_list: pwd_str = '有提取码' if folder.has_pwd else '' print(f"{folder.name}/ {folder.desc} {pwd_str}") for file in self._file_list: pwd_str = '有提取码' if file.has_pwd else '' print( f"{file.name} 大小:{file.size} 上传时间:{file.time} 下载次数:{file.downs} {pwd_str}" ) else: # 普通用户显示方式 for folder in self._dir_list: pwd_str = '✦' if folder.has_pwd else '✧' print("#{0:<12}{1:<4}{2}{3}/".format( folder.id, pwd_str, text_align(folder.desc, 28), folder.name)) for file in self._file_list: pwd_str = '✦' if file.has_pwd else '✧' print("#{0:<12}{1:<4}{2:<12}{3:>8}{4:>6} {5}".format( file.id, pwd_str, file.time, file.size, file.downs, file.name)) def cd(self, dir_name): """切换工作目录""" if not dir_name: info('cd .. 返回上级路径, cd - 返回上次路径, cd / 返回根目录') elif dir_name == '..': self.refresh(self._parent_id) elif dir_name == '/': self.refresh(-1) elif dir_name == '-': self.refresh(self._last_work_id) elif dir_name == '.': pass elif folder := self._dir_list.find_by_name(dir_name): self.refresh(folder.id) else:
File = namedtuple( 'File', ['name', 'id', 'time', 'size', 'type', 'downs', 'has_pwd', 'has_des']) Folder = namedtuple('Folder', ['name', 'id', 'has_pwd', 'desc']) FolderId = namedtuple('FolderId', ['name', 'id', 'desc', 'now']) RecFile = namedtuple('RecFile', ['name', 'id', 'type', 'size', 'time']) RecFolder = namedtuple('RecFolder', ['name', 'id', 'size', 'time', 'files']) FileDetail = namedtuple( 'FileDetail', ['code', 'name', 'size', 'type', 'time', 'desc', 'pwd', 'url', 'durl'], defaults=(0, *[''] * 8)) ShareInfo = namedtuple('ShareInfo', ['code', 'name', 'url', 'pwd', 'desc', 'time', 'size'], defaults=(0, *[''] * 6)) DirectUrlInfo = namedtuple('DirectUrlInfo', ['code', 'name', 'durl']) FolderInfo = namedtuple( 'Folder', ['name', 'id', 'pwd', 'time', 'desc', 'url', 'size', 'size_int', 'count'], defaults=(*('', ) * 7, 0, 0)) FileInFolder = namedtuple('FileInFolder', ['name', 'time', 'size', 'type', 'url', 'pwd'], defaults=('', ) * 6) FolderDetail = namedtuple('FolderDetail', ['code', 'folder', 'files', 'sub_folders'], defaults=(0, FolderInfo(), FileInFolder(), FolderList())) # gui 提取界面 name.setData ShareItem = namedtuple('ShareItem', ['item', 'all', 'count', 'parrent'], defaults=('', None, 1, []))
class Commander: """蓝奏网盘命令行""" def __init__(self): self._prompt = '> ' self._disk = LanZouCloud() self._is_login = False # self._disk.ignore_limits() self._task_mgr = global_task_mgr self._dir_list = FolderList() self._file_list = FileList() self._path_list = FolderList() self._parent_id = -1 self._parent_name = '' self._work_name = '' self._work_id = -1 self._last_work_id = -1 self._reader_mode = config.reader_mode self._default_dir_pwd = config.default_dir_pwd self._disk.set_max_size(config.max_size) self._disk.set_upload_delay(config.upload_delay) @staticmethod def clear(): clear_screen() @staticmethod def help(): print_help() @staticmethod def update(): check_update() def bye(self): if self._task_mgr.has_alive_task(): info(f"有任务在后台运行, 退出请直接关闭窗口") else: exit_cmd(0) def rmode(self): """适用于屏幕阅读器用户的显示方式""" choice = input("以适宜屏幕阅读器的方式显示(y): ") if choice and choice.lower() == 'y': config.reader_mode = True self._reader_mode = True info("已启用 Reader Mode") else: config.reader_mode = False self._reader_mode = False info("已关闭 Reader Mode") @require_login def cdrec(self): """进入回收站模式""" rec = Recovery(self._disk) rec.run() self.refresh() @require_login def xghost(self): """扫描并删除幽灵文件夹""" choice = input("需要清理幽灵文件夹吗(y): ") if choice and choice.lower() == 'y': self._disk.clean_ghost_folders() info("清理已完成") else: info("清理操作已取消") @require_login def refresh(self, dir_id=None): """刷新当前文件夹和路径信息""" dir_id = self._work_id if dir_id is None else dir_id self._file_list = self._disk.get_file_list(dir_id) self._dir_list = self._disk.get_dir_list(dir_id) self._path_list = self._disk.get_full_path(dir_id) self._prompt = '/'.join(self._path_list.all_name) + ' > ' self._last_work_id = self._work_id self._work_name = self._path_list[-1].name self._work_id = self._path_list[-1].id if dir_id != -1: # 如果存在上级路径 self._parent_name = self._path_list[-2].name self._parent_id = self._path_list[-2].id def login(self): """使用 cookie 登录""" if config.cookie and self._disk.login_by_cookie( config.cookie) == LanZouCloud.SUCCESS: self._is_login = True self.refresh() return auto = input("自动读取浏览器 Cookie 登录(y): ") or "y" if auto != "y": info("请手动设置 Cookie 内容:") ylogin = input("ylogin: "******"" disk_info = input("phpdisk_info: ") or "" cookie = {"ylogin": str(ylogin), "phpdisk_info": disk_info} if not ylogin or not disk_info: error("请输入正确的 Cookie 信息") return else: cookie, browser = load_with_keys('.woozooo.com', ['ylogin', 'phpdisk_info']) if cookie: print() info(f"从 {browser} 读取用户 Cookie 成功") else: info("请在浏览器端登录账号") open_new_tab('https://pc.woozooo.com/') info("浏览器可能等待几秒才将数据写入磁盘, 请稍等") counter = 0 while not cookie: sleep(1) counter += 1 print('.', end='', flush=True) cookie, browser = load_with_keys( '.woozooo.com', ['ylogin', 'phpdisk_info']) if cookie: print() info(f"从 {browser} 读取用户 Cookie 成功") break if counter == 10: # 读取超时 ctn = input("\n暂未读取到浏览器数据, 继续扫描(y) :") or "y" if ctn == "y": counter = 0 continue else: error("自动读取 Cookie 失败") return # 登录蓝奏云 if self._disk.login_by_cookie(cookie) == LanZouCloud.SUCCESS: config.cookie = cookie self._is_login = True self.refresh() else: error("登录失败,请检查 Cookie 是否正确") @require_login def logout(self): """注销""" clear_screen() self._prompt = '> ' self._disk.logout() self._is_login = False self._file_list.clear() self._dir_list.clear() self._path_list = FolderList() self._parent_id = -1 self._work_id = -1 self._last_work_id = -1 self._parent_name = '' self._work_name = '' config.cookie = None info("本地 Cookie 已清除") @require_login def ls(self): """列出文件(夹)""" if self._reader_mode: # 方便屏幕阅读器阅读 for folder in self._dir_list: pwd_str = '有提取码' if folder.has_pwd else '' print(f"{folder.name}/ {folder.desc} {pwd_str}") for file in self._file_list: pwd_str = '有提取码' if file.has_pwd else '' print( f"{file.name} 大小:{file.size} 上传时间:{file.time} 下载次数:{file.downs} {pwd_str}" ) else: # 普通用户显示方式 for folder in self._dir_list: pwd_str = '◆' if folder.has_pwd else '◇' print("#{0:<12}{1:<2}{2}{3}/".format( folder.id, pwd_str, text_align(folder.desc, 28), folder.name)) for file in self._file_list: pwd_str = '◆' if file.has_pwd else '◇' print("#{0:<12}{1:<2}{2:<12}{3:>8}{4:>6}↓ {5}".format( file.id, pwd_str, file.time, file.size, file.downs, file.name)) @require_login def cd(self, dir_name): """切换工作目录""" if not dir_name: info('cd .. 返回上级路径, cd - 返回上次路径, cd / 返回根目录') elif dir_name == '..': self.refresh(self._parent_id) elif dir_name == '/': self.refresh(-1) elif dir_name == '-': self.refresh(self._last_work_id) elif dir_name == '.': pass elif folder := self._dir_list.find_by_name(dir_name): self.refresh(folder.id) else: