forked from Podshot/MCEdit-Unified
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ftp_client.py
162 lines (147 loc) · 6.86 KB
/
ftp_client.py
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import ftputil
import os
import shutil
from ftputil.error import PermanentError
class CouldNotFindPropertiesException(Exception):
"""
An Exception that is raised when the 'server.properties' file could not be found at the default directory of the FTP Server
"""
pass
class CouldNotFindWorldFolderException(Exception):
"""
An Exception that is raised when the world directory that is specified in the the 'server.properties' cannot be found
"""
pass
class InvalidCreditdentialsException(Exception):
"""
An Exception that is raised when the supplied Username/Password is denied by the FTP Server
"""
pass
class FTPClient:
"""
Wrapper client to download and upload worlds to a FTP Server
"""
def download(self):
"""
Downloads all files in the current FTP directory with their corresponding paths
"""
for root, directory, files in self._host.walk(self._host.curdir):
try:
os.makedirs(os.path.join('ftp', self._worldname, root[2:]))
except OSError:
pass
for f in files:
self._host.download(self._host.path.join(root, f), os.path.join('ftp', self._worldname, root, f))
def upload_new_world(self, world):
"""
Uploads a new world to the current FTP server connection
:param world: The InfiniteWorld object for the world to upload
:type world: InfiniteWorld
"""
path = world.worldFolder.getFilePath("level.dat")[:-10]
world_name = path.split(os.path.sep)[-1]
if not self._host.path.exists(world_name):
self._host.mkdir(world_name)
self._host.chdir(world_name)
for root, directory, files in os.walk(world.worldFolder.getFilePath("level.dat")[:-10]):
for folder in directory:
target = self._host.path.join(root.replace(path, ""), folder).replace("\\", "", 1).replace("\\", "/")
print "Target: "+target
if not "##MCEDIT.TEMP##" in target:
if not self._host.path.exists(target):
self._host.makedirs(target)
for root, directory, files in os.walk(world.worldFolder.getFilePath("level.dat")[:-10]):
for f in files:
target = self._host.path.join(root.replace(path, ""), f).replace("\\", "", 1).replace("\\", "/")
print target
try:
self._host.upload(os.path.join(root, f), target)
except Exception as e:
if "226" in e.message:
pass
else:
print "Error: {0}".format(e.message)
def upload(self):
"""
Uploads an edited world to the current FTP server connection
"""
for root, directory, files in os.walk(os.path.join('ftp', self._worldname)):
for folder in directory:
target = self._host.path.join(root, folder).replace("ftp"+os.path.sep+self._worldname+"/", "").replace("\\", "", 1).replace("\\", "/")
target = target.replace("ftp"+self._worldname, "")
if not "##MCEDIT.TEMP##" in target:
if not self._host.path.exists(target):
self._host.makedirs(target)
for root, directory, files in os.walk(os.path.join('ftp', self._worldname)):
for f in files:
if self._host.path.join(root, f).replace("ftp"+os.path.sep+self._worldname, "").startswith("\\"):
target = self._host.path.join(root, f).replace("ftp"+os.path.sep+self._worldname, "").replace("\\", "", 1)
else :
target = self._host.path.join(root, f).replace("ftp"+os.path.sep+self._worldname, "")
if "\\" in target:
target = target.replace("\\", "/")
try:
self._host.upload(os.path.join(root, f), target)
except Exception as e:
if "226" in e.message:
pass
def cleanup(self):
"""
Closes the FTP connection and removes all leftover files from the 'ftp' directory
"""
if hasattr(self, '_host'):
self._host.close()
shutil.rmtree('ftp')
def safe_download(self):
"""
Changes the FTP client's working directory, downloads the world, then switches back to the original working directory
"""
old_dir = self._host.curdir
self._host.chdir(self._worldname)
self.download()
self._host.chdir(old_dir)
def get_level_path(self):
"""
Gets the local path to the downloaded FTP world
"""
return os.path.join('ftp', self._worldname)
def __init__(self, ip, username='anonymous', password=''):
"""
Initializes an FTP client to handle uploading and downloading of a Minecraft world via FTP
:param ip: The IP of the FTP Server
:type ip: str
:param username: The Username to use to log into the server
:type username: str
:param password: The Password that accompanies the supplied Username
:type password: str
"""
try:
os.mkdir("ftp")
except OSError:
pass
try:
self._host = ftputil.FTPHost(ip, username, password)
except PermanentError:
raise InvalidCreditdentialsException("Incorrect username or password")
self._worldname = None
if 'server.properties' in self._host.listdir(self._host.curdir):
self._host.download('server.properties', os.path.join('ftp', 'server.properties'))
with open(os.path.join('ftp', 'server.properties'), 'r') as props:
content = props.readlines()
if len(content) > 1:
for prop in content:
if prop.startswith("level-name"):
self._worldname = str(prop.split("=")[1:][0]).rstrip("\n")
else:
for prop in content[0].split('\r'):
if prop.startswith("level-name"):
self._worldname = str(prop.split("=")[1:][0]).rstrip("\r")
else:
raise CouldNotFindPropertiesException("Could not find the server.properties file! The FTP client will not be able to download the world unless the server.properties file is in the default FTP directory")
if self._worldname in self._host.listdir(self._host.curdir):
try:
os.mkdir(os.path.join('ftp', self._worldname))
except OSError:
pass
else:
raise CouldNotFindWorldFolderException("Could not find the world folder from the server.properties file")