From 8923b28f60cd2b2aebb7ee4ec0c1d6ada627ef8f Mon Sep 17 00:00:00 2001 From: Kyle K <kylek389@gmail.com> Date: Sun, 27 Sep 2020 02:54:25 -0500 Subject: xbox og ftp transfer utility helper for 2TB of game data --- xbox_og_ftp_helper.py | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 xbox_og_ftp_helper.py (limited to 'xbox_og_ftp_helper.py') diff --git a/xbox_og_ftp_helper.py b/xbox_og_ftp_helper.py new file mode 100644 index 0000000..d69a4e6 --- /dev/null +++ b/xbox_og_ftp_helper.py @@ -0,0 +1,131 @@ +import os +import argparse +import operator +import pathlib +import py7zr +from ftplib import FTP + +# pip install py7zr + + +def humanize_bytes(bytes, precision=1): + """Return a humanized string representation of a number of bytes. + >>> humanize_bytes(1024*12342) + '12.1 MB' + """ + + abbrevs = ( + (1<<50, 'PB'), + (1<<40, 'TB'), + (1<<30, 'GB'), + (1<<20, 'MB'), + (1<<10, 'kB'), + (1, 'b') + ) + if bytes == 1: + return '1b' + for factor, suffix in abbrevs: + if bytes >= factor: + break + return '%.*f%s' % (precision, bytes / factor, suffix) + + +def get_dir_size(path): + dirSize = 0 + for dirName, subdirList, fileList in os.walk(path): + try: + dirSize += sum(os.path.getsize(os.path.join(dirName, name)) for name in fileList) + except OSError: + pass + return dirSize + + +def myftp_connect(addr, user, passwd, dest): + try: + ftp = FTP("192.168.1.123") + ftp.login("xbox", "xbox") + ftp.cwd(dest) + return ftp + except Exception as e: + print(e) + return None + + +# pathnames should not contain trailing slash! +# 3rd param is e.g. F:\\Games\\Ford Racing 2 +def upload_dir(ftp, localdir, ftpdir): + try: + if (ftp.pwd() == '/'): + ftp.cwd(os.path.dirname(ftpdir)) # runs initially to cd into e.g. F:\\Games + ftp.mkd(os.path.basename(ftpdir)) + ftp.cwd(os.path.basename(ftpdir)) # .cwd() expects relative path + except Exception as e: + print(e) + raise + + localdir = os.path.join(localdir, '') # append slash at the end if not already there + ftpdir = os.path.join(ftpdir, '') # append slash at the end if not already there + + for fname in os.listdir(localdir): + if os.path.isdir(localdir + fname): + upload_dir(ftp, localdir + fname, ftpdir + fname) + else: + print('STOR ' + ftpdir + fname) + with open(localdir + fname, 'rb') as f: + try: + ftp.storbinary('STOR ' + fname, f) + except Exception as e: + print(e) + pass + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--addr", help="XBOX IPv4 address", required=True) + parser.add_argument("--user", default="xbox", help="ftp user (default: xbox)") + parser.add_argument("--pass", dest='passwd', default="xbox", help="ftp password (default: xbox)") + parser.add_argument("--list", help="list games currently present on XBOX", action="store_true") + parser.add_argument("--dryrun", help="dry run without actually transferring files", action="store_true") + parser.add_argument("--path", dest='src', default=".", help="path to source directory (default: current directory)") + parser.add_argument("--dest", dest='dst', default="F:\\Games\\", help="destination path (default: F:\\Games)") + args = parser.parse_args() + + path = pathlib.Path(args.src).resolve() + print("ftp credentials..: %s %s/%s\nsource...........: %s\ndestination......: %s\n" % (args.addr, args.user, args.passwd, path, args.dst)) + + if not args.dryrun: + ftp = myftp_connect(args.addr, args.user, args.passwd, args.dst) + if ftp is None: + exit(1) + + if args.list and not args.dryrun: + print("[listing] %s" % args.dst) + ftp.dir() + ftp.quit() + exit(0) + + for f in os.listdir(path): + fullpath = os.path.join(path, f) + if os.path.isdir(fullpath): + print("[transferring] %s | %9s" % (fullpath, humanize_bytes(get_dir_size(fullpath)))) + if not args.dryrun: + upload_dir(ftp, fullpath, os.path.join(args.dst, f)) + elif os.path.isfile(fullpath): + if pathlib.Path(fullpath).suffix == '.7z': + with py7zr.SevenZipFile(fullpath, mode='r') as z: + print("[extracting] %s | %9s" % (fullpath, os.path.getsize(fullpath))) + if not args.dryrun: + try: + z.extractall('_tmp') + except Exception as e: + pass + for root, dirs, files in os.walk('_tmp'): + if 'default.xbe' in files: + break + print("root of extracted .7z game is: %s" % (root)) + upload_dir(ftp, os.path.join(os.path.dirname(fullpath), root), os.path.join(args.dst, f)) + else: + pass + #print("%s %s" % (f, 'not a directory or .7z file')) + ftp.quit() + -- cgit v1.2.3