summaryrefslogtreecommitdiffstats
path: root/xbox_og_ftp_helper.py
blob: d69a4e642c2b04164581e6fc4f98e039d53a4932 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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()