gofilepy.gofile
1import requests 2import os 3from io import BufferedReader 4from .exceptions import GofileAPIException 5 6 7GofileFile = None 8GofileFolder = None 9GofileAccount = None 10 11class GofileClient (object): 12 server = None 13 BASE_DOMAIN = 'gofile.io' 14 API_SUBDOMAIN = 'api' 15 BASE_API_URL = 'https://'+API_SUBDOMAIN+'.'+BASE_DOMAIN 16 17 API_ROUTE_GET_SERVER_URL = BASE_API_URL + '/getServer' 18 API_ROUTE_GET_ACCOUNT_URL = BASE_API_URL + "/getAccountDetails" 19 API_ROUTE_GET_CONTENT_URL = BASE_API_URL + "/getContent" 20 21 API_ROUTE_DELETE_CONTENT_URL = BASE_API_URL + "/deleteContent" 22 API_ROUTE_COPY_CONTENT_URL = BASE_API_URL + "/copyContent" 23 API_ROUTE_CREATE_FOLDER_URL = BASE_API_URL + "/createFolder" 24 API_ROUTE_SET_OPTION_URL = BASE_API_URL + "/setOption" 25 26 API_ROUTE_DOWNLOAD_PATH = "download" 27 API_ROUTE_UPLOAD_CONTENT_PATH = "uploadFile" 28 29 API_STORE_FORMAT = "https://{}.{}/{}" 30 31 def __init__(self, token: str = None, get_account: bool = True, verbose: bool = False): 32 self.token = token 33 self.server = GofileClient.get_best_server() 34 self.verbose = verbose 35 36 if get_account and token: 37 self.get_account() 38 39 @staticmethod 40 def handle_response(resp: requests.Response): 41 code = resp.status_code 42 data = resp.json() 43 got = None 44 api_status = '' 45 46 if data: 47 api_status = data.get('status') 48 got = data.get('data') 49 50 51 if api_status != 'ok' or code != 200: 52 raise GofileAPIException.__init_from_resp__(resp) 53 return got 54 55 def get_best_upload_url(self): 56 return self.API_STORE_FORMAT.format(self.server, self.BASE_DOMAIN, self.API_ROUTE_UPLOAD_CONTENT_PATH) 57 58 59 @staticmethod 60 def get_best_server(throw_if_not_200=False): 61 resp = requests.get(GofileClient.API_ROUTE_GET_SERVER_URL) 62 return GofileClient.handle_response(resp)['server'] 63 64 65 def _download_file_from_direct_link(self, direct_link, out_dir="./"): 66 fn = direct_link.rsplit('/', 1)[1] 67 resp = requests.get(direct_link, stream=True, allow_redirects=None) 68 if resp.status_code != 200: 69 raise GofileAPIException("Could not download file", code=resp.status_code) 70 71 out_path = os.path.join(out_dir, fn) 72 with open(out_path, 'wb') as f: 73 for chunk in resp.iter_content(chunk_size=1024): 74 if chunk: 75 f.write(chunk) 76 return out_path 77 78 79 def _get_token(self, token): 80 if not token: 81 token = self.token 82 if not self.token: 83 token = "" 84 return token 85 86 def upload(self, path: str=None, file: BufferedReader=None, parent_id: str=None, token: str=None) -> GofileFile: 87 if not file and not path: 88 raise ValueError("GofileClient.upload() requires a BufferedReader or file path") 89 90 upload_url = self.get_best_upload_url() 91 token = self._get_token(token) 92 93 data = {} 94 if parent_id: 95 data["folderId"] = parent_id 96 if token: 97 data["token"] = token 98 99 files = {} 100 if file: 101 files["file"] = file 102 elif path: 103 files["file"] = open(path, "rb") 104 105 resp = requests.post(upload_url, files=files, data=data) 106 got = GofileClient.handle_response(resp) 107 108 #Needed because json returned from API has different key values at this endpoint 109 got["id"] = got.get("fileId", None) 110 got["name"] = got.get("fileName", None) 111 112 return GofileFile._load_from_dict(got, client=self) 113 114 115 def _get_content_raw_resp(self, content_id: str, token: str = None): 116 token = self._get_token(token) 117 req_url = self.API_ROUTE_GET_CONTENT_URL + "?contentId="+content_id 118 119 if token: 120 req_url += "&token="+token 121 122 resp = requests.get(req_url) 123 data = GofileClient.handle_response(resp) 124 return resp, data 125 126 127 def get(self, content_id: str, token: str = None): 128 resp,data = self._get_content_raw_resp(content_id, token=token) 129 return GofileContent.__init_from_resp__(resp, client=self) 130 131 def get_folder(self, *args, **kwargs): 132 """Retrieves folder using content_id""" 133 return self.get(*args, **kwargs) 134 135 def delete(self, *content_ids: str, token: str = None): 136 """Calls Gofile API to delete provided content_ids.""" 137 token = self._get_token(token) 138 data = {"contentsId": ",".join(content_ids), "token": token} 139 resp = requests.delete(GofileClient.API_ROUTE_DELETE_CONTENT_URL, data=data) 140 got = GofileClient.handle_response(resp) 141 142 143 def _get_account_raw_resp(self, token: str = None): 144 token = self._get_token(token) 145 url = GofileClient.API_ROUTE_GET_ACCOUNT_URL + "?token=" + token 146 resp = requests.get(url) 147 data = GofileClient.handle_response(resp) 148 return resp, data 149 150 151 def get_account(self, token: str = None) -> GofileAccount: 152 """If token is provided returns specified account, otherwise token defaults to self.token. 153 \If token is default self.account is updated""" 154 token = self._get_token(token) 155 resp, data = self._get_account_raw_resp(token=token) 156 account = GofileAccount._load_from_dict(data) 157 account._client = self 158 account._raw = data 159 160 if account.token == self.token: 161 self.account = account #update client's copy of account 162 163 return account 164 165 def set_content_option(self, content_id: str, option: str, value, token: str = None): 166 """Sets content option like 'description', 'public', etc (more at gofile.io/api). Note that folder and file content have different options""" 167 token = self._get_token(token) 168 169 if type(value) == bool: #api expects bools to be string 170 if value: 171 value = "true" 172 else: 173 value = "false" 174 175 data = { 176 "contentId": content_id, 177 "token": token, 178 "option": option, 179 "value": value 180 } 181 182 resp = requests.put(GofileClient.API_ROUTE_SET_OPTION_URL, data=data) 183 got = GofileClient.handle_response(resp) 184 185 186 def copy_content(self, *content_ids: str, parent_id: str = None, token: str = None): 187 """Copy provided content_ids to destination folder's content_id. Currently returns None because api doesn't return any information. Will have to query parent folder""" 188 if not parent_id: 189 raise ValueError("Must pass a parent folder id: parent_id=None") 190 191 token = self._get_token(token) 192 data = { 193 "contentsId": ",".join(content_ids), 194 "folderIdDest": parent_id, 195 "token": token 196 } 197 198 resp = requests.put(GofileClient.API_ROUTE_COPY_CONTENT_URL, data=data) 199 got = GofileClient.handle_response(resp) 200 201 """ 202 As of right now /copyContent does not return information about newly created content 203 For this reason copy_content will just return None 204 205 return GofileContent.__init_from_resp__(resp, client=self) 206 """ 207 208 def create_folder(self, name: str, parent_id: str, token: str = None): 209 """Creates folder in specified parent folder's content_id""" 210 token = self._get_token(token) 211 212 data = { 213 "parentFolderId": parent_id, 214 "folderName": name 215 } 216 217 data["token"] = token 218 219 resp = requests.put(GofileClient.API_ROUTE_CREATE_FOLDER_URL, data=data) 220 got = GofileClient.handle_response(resp) 221 222 return GofileContent.__init_from_resp__(resp, client=self) 223 224class GofileAccount (object): 225 token: str 226 """Token of account, found on Gofile.io""" 227 email: str 228 """Email address of account""" 229 tier: str 230 """Tier of GofileAccount either Standard or Premium""" 231 root_id: str 232 """Root folder's content_id of Gofile account""" 233 folder_cnt: int 234 """Number of children folders""" 235 file_cnt: int 236 """Number of children files""" 237 total_size: int 238 """Total size of Accounts' contents""" 239 total_download_cnt: int 240 """Total download count of Accounts' contents""" 241 242 def __init__(self, token: str = None): 243 self.token = token 244 self.email = None 245 self.tier = None 246 self.root_id = None 247 self.folder_cnt = None 248 self.file_cnt = None 249 self.total_size = None 250 self.total_download_cnt = None 251 self._raw = {} 252 253 def _override_from_dict(self, data: dict) -> None: 254 self.token = data.get("token", self.token) 255 self.email = data.get("email", self.email) 256 self.tier = data.get("tier", self.tier) 257 self.root_id = data.get("rootFolder", self.root_id) 258 self.folder_cnt = data.get("foldersCount", self.folder_cnt) 259 self.file_cnt = data.get("filesCount", self.file_cnt) 260 self.total_size = data.get("totalSize", self.total_size) 261 self.total_download_cnt = data.get("totalDownloadCount", self.total_download_cnt) 262 263 self._raw = data 264 265 @staticmethod 266 def _load_from_dict(data: dict): 267 account = GofileAccount(data["token"]) 268 account._override_from_dict(data) 269 return account 270 271 def reload(self): 272 resp, data = self._client._get_account_raw_resp(token=self.token) 273 self._override_from_dict(data) 274 self._raw = data 275 276class GofileContent (object): 277 name: str 278 """Name of content""" 279 content_id: str 280 """Gofile API's unique content id""" 281 parent_id: str 282 """Content_id of parent folder""" 283 _type: str 284 """GofileContent subtypes, either 'file', 'folder' or 'unknown'.""" 285 is_file_type: bool 286 """If GofileContent is a file""" 287 is_folder_type: bool 288 """If GofileContent is a folder""" 289 is_unknown_type: bool 290 """If GofileContent is unknown (call reload() to update)""" 291 is_deleted: bool 292 """If content is deleted (will only register if called by it's own method delete())""" 293 294 def __init__(self, content_id: str, parent_id: str, _type: str = None, client: GofileClient = None): 295 self.content_id = content_id 296 self.parent_id = parent_id 297 self._type = _type 298 self._client = client 299 self._raw = {} 300 301 self.is_file_type = _type == "file" 302 self.is_folder_type = _type == "folder" 303 self.is_unknown_type = _type == None 304 self.name = None 305 self.time_created = None 306 self.is_deleted = False 307 308 def __repr__ (self) -> str: 309 _type = self._type 310 if not _type: 311 _type = "Unknown" 312 313 return "<Gofile {}: content_id={} name={}>".format(_type.upper(), self.content_id, self.name) 314 315 def delete (self) -> None: 316 """Deletes itself. When called successfully is_deleted = True""" 317 guest_token = self._raw.get("guestToken") 318 self._client.delete(self.content_id, token=guest_token) 319 self.is_deleted = True 320 321 def copy_to (self, dest_id: str) -> None: 322 """Copies itself to destination folder's content_id""" 323 self._client.copy_content(self.content_id, parent_id=dest_id) 324 325 def copy (self, dest_id: str) -> None: 326 self.copy_to(dest_id) 327 328 def set_option(self, option: str, value, reload: bool = True) -> None: 329 """Sets options for itself. Full option list available at gofile.io/api""" 330 self._client.set_content_option(self.content_id, option, value) 331 if reload: 332 self.reload() #reload to get up to date information 333 334 def reload (self): 335 """Reloads any new updates to content. If is_unknown_type = True then reload() returns updated content""" 336 if self.is_folder_type or (self.is_unknown_type and self.parent_id == None): 337 resp, data = self._client._get_content_raw_resp(self.content_id) 338 339 if self.is_unknown_type: 340 content = GofileContent.__init_from_resp__(resp, client=self._client) 341 342 elif self.is_folder_type: 343 self._override_from_dict(data) 344 return self 345 346 elif (self.is_unknown_type or self.is_file_type) and self.parent_id: 347 resp, data = self._client._get_content_raw_resp(self.parent_id) 348 content_data = data["contents"].get(self.content_id, None) 349 content = None 350 if content_data: 351 content = GofileContent.__init_from_resp__({"data": content_data}, client=self._client) 352 353 if self.is_file_type: 354 self._override_from_dict(content_data) 355 356 return content 357 358 else: 359 raise NotImplemented 360 361 @staticmethod 362 def __init_from_resp__ (resp: requests.Response, _type: str = None, client: GofileClient = None): 363 if type(resp) == requests.models.Response: 364 resp = resp.json() 365 366 got = resp["data"] 367 _type = got.get("type", _type) 368 content = None 369 370 if _type == "file": 371 content = GofileFile._load_from_dict(got, client=client) 372 elif _type == "folder": 373 content = GofileFolder._load_from_dict(got, client=client) 374 else: 375 raise NotImplemented 376 377 return content 378 379class GofileFile (GofileContent): 380 time_created: int 381 """Time that file was uploaded""" 382 size: int 383 """Size of file (in bytes)""" 384 download_cnt: int 385 """Amount of times the file has been downloaded""" 386 mimetype: str 387 """Mimetype of file""" 388 server: str 389 """subdomain server from where file will be downloaded (Premium)""" 390 direct_link: str 391 """Direct link to download file (Premium)""" 392 page_link: str 393 """Page link to view and get download url for file""" 394 md5: str 395 """Hash function of file for verification""" 396 397 def __init__(self, content_id: str, parent_id: str, client: GofileClient = None): 398 super().__init__(content_id, parent_id, _type="file", client=client) 399 self.name = None 400 self.time_created = None 401 self.size = None 402 self.download_cnt = None 403 self.mimetype = None 404 self.server = None 405 self.direct_link = None 406 self.page_link = None 407 self.md5 = None 408 409 def _override_from_dict(self, data: dict) -> None: 410 self.content_id = data.get("id", self.content_id) 411 self.parent_id = data.get("parentFolder", self.parent_id) 412 self.name = data.get("name", self.name) 413 self.time_created = data.get("createTime", self.time_created) 414 self.size = data.get("size", self.size) 415 self.download_cnt = data.get("downloadCount", self.download_cnt) 416 self.mimetype = data.get("mimetype", self.mimetype) 417 self.md5 = data.get("md5", self.md5) 418 self.server = data.get("serverChoosen", None) 419 link = data.get("link") 420 if link: 421 self.direct_link = self._get_direct_link_from_link(link) 422 self.page_link = data.get("downloadPage", self.page_link) 423 424 self._raw = data 425 426 @staticmethod 427 def _get_direct_link_from_link (link): 428 idx = link.find("download/") + len("download/")-1 429 return link[:idx] + "/direct/" + link[idx+1:] 430 431 @staticmethod 432 def _load_from_dict(data: dict, client: GofileClient = None): 433 file = GofileFile(data["id"], data["parentFolder"], client=client) 434 file._override_from_dict(data) 435 file._raw = data 436 return file 437 438 def download(self, out_dir: str = "./") -> str: 439 """Downloads file to passed dir (default is working directory). Note: The option directLink 440 \needs to be True (Premium)""" 441 442 if self.direct_link: 443 return self._client._download_file_from_direct_link(self.direct_link, out_dir=out_dir) 444 445 else: 446 raise Exception("Direct link needed - set option directLink=True (only for premium users)") 447 448class GofileFolder (GofileContent): 449 children: list[GofileContent] 450 """Children of folder, either GofileFolder or GofileFile type""" 451 children_ids: list[str] 452 """List of childrens' content ids""" 453 time_created: int 454 """Time folder was created""" 455 total_size: int 456 """Total size of folders' contents (in bytes)""" 457 is_public: bool 458 """Is folder publicly accessible""" 459 is_owner: bool 460 """If caller is folder owner""" 461 is_root: bool 462 """If folder is root folder""" 463 has_password: bool 464 """If folder is password protected""" 465 code: str 466 """Folder shortcode to access from the browser""" 467 468 def __init__(self, name: str, content_id: str, parent_id: str, client: GofileClient = None): 469 super().__init__(content_id, parent_id, _type="folder", client=client) 470 self.name = name 471 self.children = [] 472 self.children_ids = [] 473 self.total_size = None 474 self.total_download_cnt = None 475 self.time_created = None 476 self.is_public = None 477 self.is_owner = None 478 self.is_root = None 479 self.has_password = None 480 self.code = None 481 482 def __init_children_from_contents__(self, data: dict) -> None: 483 children = [] 484 485 self.children_ids = data.get("childs") 486 contents = data.get("contents", {}) 487 488 if contents.keys(): 489 for content in contents.values(): 490 child = GofileContent.__init_from_resp__({"data": content}, client=self._client) 491 children.append(child) 492 493 elif self.children_ids: 494 for child_id in self.children_ids: 495 child = GofileContent(child_id, parent_id=data["id"], client=self._client) 496 children.append(child) 497 return children 498 499 500 def _override_from_dict(self, data: dict) -> None: 501 self.content_id = data.get("id", self.content_id) 502 self.parent_id = data.get("parentFolder", self.parent_id) 503 self.name = data.get("name", self.name) 504 self.time_created = data.get("createTime", self.time_created) 505 self.is_public = data.get("public", self.is_public) 506 self.is_owner = data.get("isOwner", self.is_owner) 507 self.is_root = data.get("isRoot", False) 508 self.has_password = data.get("password", self.has_password) 509 self.code = data.get("code", self.code) 510 self.total_size = data.get("totalSize", self.total_size) 511 self.total_download_cnt = data.get("totalDownloadCount", self.total_download_cnt) 512 self.children_ids = data.get("childs") 513 514 self.children = self.__init_children_from_contents__(data) 515 516 self._raw = data 517 518 519 @staticmethod 520 def _load_from_dict(data: dict, client: GofileClient = None) -> GofileFolder: 521 parent_id = data.get("parentFolder", None) 522 folder = GofileFolder(data["name"], data["id"], parent_id, client=client) 523 folder._override_from_dict(data) 524 folder._raw = data 525 526 return folder 527 528 def upload(self, path: str = None, file: BufferedReader = None) -> GofileFile: 529 return self._client.upload(file=file, path=path, parent_id=self.content_id)
380class GofileFile (GofileContent): 381 time_created: int 382 """Time that file was uploaded""" 383 size: int 384 """Size of file (in bytes)""" 385 download_cnt: int 386 """Amount of times the file has been downloaded""" 387 mimetype: str 388 """Mimetype of file""" 389 server: str 390 """subdomain server from where file will be downloaded (Premium)""" 391 direct_link: str 392 """Direct link to download file (Premium)""" 393 page_link: str 394 """Page link to view and get download url for file""" 395 md5: str 396 """Hash function of file for verification""" 397 398 def __init__(self, content_id: str, parent_id: str, client: GofileClient = None): 399 super().__init__(content_id, parent_id, _type="file", client=client) 400 self.name = None 401 self.time_created = None 402 self.size = None 403 self.download_cnt = None 404 self.mimetype = None 405 self.server = None 406 self.direct_link = None 407 self.page_link = None 408 self.md5 = None 409 410 def _override_from_dict(self, data: dict) -> None: 411 self.content_id = data.get("id", self.content_id) 412 self.parent_id = data.get("parentFolder", self.parent_id) 413 self.name = data.get("name", self.name) 414 self.time_created = data.get("createTime", self.time_created) 415 self.size = data.get("size", self.size) 416 self.download_cnt = data.get("downloadCount", self.download_cnt) 417 self.mimetype = data.get("mimetype", self.mimetype) 418 self.md5 = data.get("md5", self.md5) 419 self.server = data.get("serverChoosen", None) 420 link = data.get("link") 421 if link: 422 self.direct_link = self._get_direct_link_from_link(link) 423 self.page_link = data.get("downloadPage", self.page_link) 424 425 self._raw = data 426 427 @staticmethod 428 def _get_direct_link_from_link (link): 429 idx = link.find("download/") + len("download/")-1 430 return link[:idx] + "/direct/" + link[idx+1:] 431 432 @staticmethod 433 def _load_from_dict(data: dict, client: GofileClient = None): 434 file = GofileFile(data["id"], data["parentFolder"], client=client) 435 file._override_from_dict(data) 436 file._raw = data 437 return file 438 439 def download(self, out_dir: str = "./") -> str: 440 """Downloads file to passed dir (default is working directory). Note: The option directLink 441 \needs to be True (Premium)""" 442 443 if self.direct_link: 444 return self._client._download_file_from_direct_link(self.direct_link, out_dir=out_dir) 445 446 else: 447 raise Exception("Direct link needed - set option directLink=True (only for premium users)")
398 def __init__(self, content_id: str, parent_id: str, client: GofileClient = None): 399 super().__init__(content_id, parent_id, _type="file", client=client) 400 self.name = None 401 self.time_created = None 402 self.size = None 403 self.download_cnt = None 404 self.mimetype = None 405 self.server = None 406 self.direct_link = None 407 self.page_link = None 408 self.md5 = None
439 def download(self, out_dir: str = "./") -> str: 440 """Downloads file to passed dir (default is working directory). Note: The option directLink 441 \needs to be True (Premium)""" 442 443 if self.direct_link: 444 return self._client._download_file_from_direct_link(self.direct_link, out_dir=out_dir) 445 446 else: 447 raise Exception("Direct link needed - set option directLink=True (only for premium users)")
Downloads file to passed dir (default is working directory). Note: The option directLink
eeds to be True (Premium)
Inherited Members
449class GofileFolder (GofileContent): 450 children: list[GofileContent] 451 """Children of folder, either GofileFolder or GofileFile type""" 452 children_ids: list[str] 453 """List of childrens' content ids""" 454 time_created: int 455 """Time folder was created""" 456 total_size: int 457 """Total size of folders' contents (in bytes)""" 458 is_public: bool 459 """Is folder publicly accessible""" 460 is_owner: bool 461 """If caller is folder owner""" 462 is_root: bool 463 """If folder is root folder""" 464 has_password: bool 465 """If folder is password protected""" 466 code: str 467 """Folder shortcode to access from the browser""" 468 469 def __init__(self, name: str, content_id: str, parent_id: str, client: GofileClient = None): 470 super().__init__(content_id, parent_id, _type="folder", client=client) 471 self.name = name 472 self.children = [] 473 self.children_ids = [] 474 self.total_size = None 475 self.total_download_cnt = None 476 self.time_created = None 477 self.is_public = None 478 self.is_owner = None 479 self.is_root = None 480 self.has_password = None 481 self.code = None 482 483 def __init_children_from_contents__(self, data: dict) -> None: 484 children = [] 485 486 self.children_ids = data.get("childs") 487 contents = data.get("contents", {}) 488 489 if contents.keys(): 490 for content in contents.values(): 491 child = GofileContent.__init_from_resp__({"data": content}, client=self._client) 492 children.append(child) 493 494 elif self.children_ids: 495 for child_id in self.children_ids: 496 child = GofileContent(child_id, parent_id=data["id"], client=self._client) 497 children.append(child) 498 return children 499 500 501 def _override_from_dict(self, data: dict) -> None: 502 self.content_id = data.get("id", self.content_id) 503 self.parent_id = data.get("parentFolder", self.parent_id) 504 self.name = data.get("name", self.name) 505 self.time_created = data.get("createTime", self.time_created) 506 self.is_public = data.get("public", self.is_public) 507 self.is_owner = data.get("isOwner", self.is_owner) 508 self.is_root = data.get("isRoot", False) 509 self.has_password = data.get("password", self.has_password) 510 self.code = data.get("code", self.code) 511 self.total_size = data.get("totalSize", self.total_size) 512 self.total_download_cnt = data.get("totalDownloadCount", self.total_download_cnt) 513 self.children_ids = data.get("childs") 514 515 self.children = self.__init_children_from_contents__(data) 516 517 self._raw = data 518 519 520 @staticmethod 521 def _load_from_dict(data: dict, client: GofileClient = None) -> GofileFolder: 522 parent_id = data.get("parentFolder", None) 523 folder = GofileFolder(data["name"], data["id"], parent_id, client=client) 524 folder._override_from_dict(data) 525 folder._raw = data 526 527 return folder 528 529 def upload(self, path: str = None, file: BufferedReader = None) -> GofileFile: 530 return self._client.upload(file=file, path=path, parent_id=self.content_id)
469 def __init__(self, name: str, content_id: str, parent_id: str, client: GofileClient = None): 470 super().__init__(content_id, parent_id, _type="folder", client=client) 471 self.name = name 472 self.children = [] 473 self.children_ids = [] 474 self.total_size = None 475 self.total_download_cnt = None 476 self.time_created = None 477 self.is_public = None 478 self.is_owner = None 479 self.is_root = None 480 self.has_password = None 481 self.code = None
Inherited Members
225class GofileAccount (object): 226 token: str 227 """Token of account, found on Gofile.io""" 228 email: str 229 """Email address of account""" 230 tier: str 231 """Tier of GofileAccount either Standard or Premium""" 232 root_id: str 233 """Root folder's content_id of Gofile account""" 234 folder_cnt: int 235 """Number of children folders""" 236 file_cnt: int 237 """Number of children files""" 238 total_size: int 239 """Total size of Accounts' contents""" 240 total_download_cnt: int 241 """Total download count of Accounts' contents""" 242 243 def __init__(self, token: str = None): 244 self.token = token 245 self.email = None 246 self.tier = None 247 self.root_id = None 248 self.folder_cnt = None 249 self.file_cnt = None 250 self.total_size = None 251 self.total_download_cnt = None 252 self._raw = {} 253 254 def _override_from_dict(self, data: dict) -> None: 255 self.token = data.get("token", self.token) 256 self.email = data.get("email", self.email) 257 self.tier = data.get("tier", self.tier) 258 self.root_id = data.get("rootFolder", self.root_id) 259 self.folder_cnt = data.get("foldersCount", self.folder_cnt) 260 self.file_cnt = data.get("filesCount", self.file_cnt) 261 self.total_size = data.get("totalSize", self.total_size) 262 self.total_download_cnt = data.get("totalDownloadCount", self.total_download_cnt) 263 264 self._raw = data 265 266 @staticmethod 267 def _load_from_dict(data: dict): 268 account = GofileAccount(data["token"]) 269 account._override_from_dict(data) 270 return account 271 272 def reload(self): 273 resp, data = self._client._get_account_raw_resp(token=self.token) 274 self._override_from_dict(data) 275 self._raw = data
12class GofileClient (object): 13 server = None 14 BASE_DOMAIN = 'gofile.io' 15 API_SUBDOMAIN = 'api' 16 BASE_API_URL = 'https://'+API_SUBDOMAIN+'.'+BASE_DOMAIN 17 18 API_ROUTE_GET_SERVER_URL = BASE_API_URL + '/getServer' 19 API_ROUTE_GET_ACCOUNT_URL = BASE_API_URL + "/getAccountDetails" 20 API_ROUTE_GET_CONTENT_URL = BASE_API_URL + "/getContent" 21 22 API_ROUTE_DELETE_CONTENT_URL = BASE_API_URL + "/deleteContent" 23 API_ROUTE_COPY_CONTENT_URL = BASE_API_URL + "/copyContent" 24 API_ROUTE_CREATE_FOLDER_URL = BASE_API_URL + "/createFolder" 25 API_ROUTE_SET_OPTION_URL = BASE_API_URL + "/setOption" 26 27 API_ROUTE_DOWNLOAD_PATH = "download" 28 API_ROUTE_UPLOAD_CONTENT_PATH = "uploadFile" 29 30 API_STORE_FORMAT = "https://{}.{}/{}" 31 32 def __init__(self, token: str = None, get_account: bool = True, verbose: bool = False): 33 self.token = token 34 self.server = GofileClient.get_best_server() 35 self.verbose = verbose 36 37 if get_account and token: 38 self.get_account() 39 40 @staticmethod 41 def handle_response(resp: requests.Response): 42 code = resp.status_code 43 data = resp.json() 44 got = None 45 api_status = '' 46 47 if data: 48 api_status = data.get('status') 49 got = data.get('data') 50 51 52 if api_status != 'ok' or code != 200: 53 raise GofileAPIException.__init_from_resp__(resp) 54 return got 55 56 def get_best_upload_url(self): 57 return self.API_STORE_FORMAT.format(self.server, self.BASE_DOMAIN, self.API_ROUTE_UPLOAD_CONTENT_PATH) 58 59 60 @staticmethod 61 def get_best_server(throw_if_not_200=False): 62 resp = requests.get(GofileClient.API_ROUTE_GET_SERVER_URL) 63 return GofileClient.handle_response(resp)['server'] 64 65 66 def _download_file_from_direct_link(self, direct_link, out_dir="./"): 67 fn = direct_link.rsplit('/', 1)[1] 68 resp = requests.get(direct_link, stream=True, allow_redirects=None) 69 if resp.status_code != 200: 70 raise GofileAPIException("Could not download file", code=resp.status_code) 71 72 out_path = os.path.join(out_dir, fn) 73 with open(out_path, 'wb') as f: 74 for chunk in resp.iter_content(chunk_size=1024): 75 if chunk: 76 f.write(chunk) 77 return out_path 78 79 80 def _get_token(self, token): 81 if not token: 82 token = self.token 83 if not self.token: 84 token = "" 85 return token 86 87 def upload(self, path: str=None, file: BufferedReader=None, parent_id: str=None, token: str=None) -> GofileFile: 88 if not file and not path: 89 raise ValueError("GofileClient.upload() requires a BufferedReader or file path") 90 91 upload_url = self.get_best_upload_url() 92 token = self._get_token(token) 93 94 data = {} 95 if parent_id: 96 data["folderId"] = parent_id 97 if token: 98 data["token"] = token 99 100 files = {} 101 if file: 102 files["file"] = file 103 elif path: 104 files["file"] = open(path, "rb") 105 106 resp = requests.post(upload_url, files=files, data=data) 107 got = GofileClient.handle_response(resp) 108 109 #Needed because json returned from API has different key values at this endpoint 110 got["id"] = got.get("fileId", None) 111 got["name"] = got.get("fileName", None) 112 113 return GofileFile._load_from_dict(got, client=self) 114 115 116 def _get_content_raw_resp(self, content_id: str, token: str = None): 117 token = self._get_token(token) 118 req_url = self.API_ROUTE_GET_CONTENT_URL + "?contentId="+content_id 119 120 if token: 121 req_url += "&token="+token 122 123 resp = requests.get(req_url) 124 data = GofileClient.handle_response(resp) 125 return resp, data 126 127 128 def get(self, content_id: str, token: str = None): 129 resp,data = self._get_content_raw_resp(content_id, token=token) 130 return GofileContent.__init_from_resp__(resp, client=self) 131 132 def get_folder(self, *args, **kwargs): 133 """Retrieves folder using content_id""" 134 return self.get(*args, **kwargs) 135 136 def delete(self, *content_ids: str, token: str = None): 137 """Calls Gofile API to delete provided content_ids.""" 138 token = self._get_token(token) 139 data = {"contentsId": ",".join(content_ids), "token": token} 140 resp = requests.delete(GofileClient.API_ROUTE_DELETE_CONTENT_URL, data=data) 141 got = GofileClient.handle_response(resp) 142 143 144 def _get_account_raw_resp(self, token: str = None): 145 token = self._get_token(token) 146 url = GofileClient.API_ROUTE_GET_ACCOUNT_URL + "?token=" + token 147 resp = requests.get(url) 148 data = GofileClient.handle_response(resp) 149 return resp, data 150 151 152 def get_account(self, token: str = None) -> GofileAccount: 153 """If token is provided returns specified account, otherwise token defaults to self.token. 154 \If token is default self.account is updated""" 155 token = self._get_token(token) 156 resp, data = self._get_account_raw_resp(token=token) 157 account = GofileAccount._load_from_dict(data) 158 account._client = self 159 account._raw = data 160 161 if account.token == self.token: 162 self.account = account #update client's copy of account 163 164 return account 165 166 def set_content_option(self, content_id: str, option: str, value, token: str = None): 167 """Sets content option like 'description', 'public', etc (more at gofile.io/api). Note that folder and file content have different options""" 168 token = self._get_token(token) 169 170 if type(value) == bool: #api expects bools to be string 171 if value: 172 value = "true" 173 else: 174 value = "false" 175 176 data = { 177 "contentId": content_id, 178 "token": token, 179 "option": option, 180 "value": value 181 } 182 183 resp = requests.put(GofileClient.API_ROUTE_SET_OPTION_URL, data=data) 184 got = GofileClient.handle_response(resp) 185 186 187 def copy_content(self, *content_ids: str, parent_id: str = None, token: str = None): 188 """Copy provided content_ids to destination folder's content_id. Currently returns None because api doesn't return any information. Will have to query parent folder""" 189 if not parent_id: 190 raise ValueError("Must pass a parent folder id: parent_id=None") 191 192 token = self._get_token(token) 193 data = { 194 "contentsId": ",".join(content_ids), 195 "folderIdDest": parent_id, 196 "token": token 197 } 198 199 resp = requests.put(GofileClient.API_ROUTE_COPY_CONTENT_URL, data=data) 200 got = GofileClient.handle_response(resp) 201 202 """ 203 As of right now /copyContent does not return information about newly created content 204 For this reason copy_content will just return None 205 206 return GofileContent.__init_from_resp__(resp, client=self) 207 """ 208 209 def create_folder(self, name: str, parent_id: str, token: str = None): 210 """Creates folder in specified parent folder's content_id""" 211 token = self._get_token(token) 212 213 data = { 214 "parentFolderId": parent_id, 215 "folderName": name 216 } 217 218 data["token"] = token 219 220 resp = requests.put(GofileClient.API_ROUTE_CREATE_FOLDER_URL, data=data) 221 got = GofileClient.handle_response(resp) 222 223 return GofileContent.__init_from_resp__(resp, client=self)
40 @staticmethod 41 def handle_response(resp: requests.Response): 42 code = resp.status_code 43 data = resp.json() 44 got = None 45 api_status = '' 46 47 if data: 48 api_status = data.get('status') 49 got = data.get('data') 50 51 52 if api_status != 'ok' or code != 200: 53 raise GofileAPIException.__init_from_resp__(resp) 54 return got
87 def upload(self, path: str=None, file: BufferedReader=None, parent_id: str=None, token: str=None) -> GofileFile: 88 if not file and not path: 89 raise ValueError("GofileClient.upload() requires a BufferedReader or file path") 90 91 upload_url = self.get_best_upload_url() 92 token = self._get_token(token) 93 94 data = {} 95 if parent_id: 96 data["folderId"] = parent_id 97 if token: 98 data["token"] = token 99 100 files = {} 101 if file: 102 files["file"] = file 103 elif path: 104 files["file"] = open(path, "rb") 105 106 resp = requests.post(upload_url, files=files, data=data) 107 got = GofileClient.handle_response(resp) 108 109 #Needed because json returned from API has different key values at this endpoint 110 got["id"] = got.get("fileId", None) 111 got["name"] = got.get("fileName", None) 112 113 return GofileFile._load_from_dict(got, client=self)
132 def get_folder(self, *args, **kwargs): 133 """Retrieves folder using content_id""" 134 return self.get(*args, **kwargs)
Retrieves folder using content_id
136 def delete(self, *content_ids: str, token: str = None): 137 """Calls Gofile API to delete provided content_ids.""" 138 token = self._get_token(token) 139 data = {"contentsId": ",".join(content_ids), "token": token} 140 resp = requests.delete(GofileClient.API_ROUTE_DELETE_CONTENT_URL, data=data) 141 got = GofileClient.handle_response(resp)
Calls Gofile API to delete provided content_ids.
152 def get_account(self, token: str = None) -> GofileAccount: 153 """If token is provided returns specified account, otherwise token defaults to self.token. 154 \If token is default self.account is updated""" 155 token = self._get_token(token) 156 resp, data = self._get_account_raw_resp(token=token) 157 account = GofileAccount._load_from_dict(data) 158 account._client = self 159 account._raw = data 160 161 if account.token == self.token: 162 self.account = account #update client's copy of account 163 164 return account
If token is provided returns specified account, otherwise token defaults to self.token. \If token is default self.account is updated
166 def set_content_option(self, content_id: str, option: str, value, token: str = None): 167 """Sets content option like 'description', 'public', etc (more at gofile.io/api). Note that folder and file content have different options""" 168 token = self._get_token(token) 169 170 if type(value) == bool: #api expects bools to be string 171 if value: 172 value = "true" 173 else: 174 value = "false" 175 176 data = { 177 "contentId": content_id, 178 "token": token, 179 "option": option, 180 "value": value 181 } 182 183 resp = requests.put(GofileClient.API_ROUTE_SET_OPTION_URL, data=data) 184 got = GofileClient.handle_response(resp)
Sets content option like 'description', 'public', etc (more at gofile.io/api). Note that folder and file content have different options
187 def copy_content(self, *content_ids: str, parent_id: str = None, token: str = None): 188 """Copy provided content_ids to destination folder's content_id. Currently returns None because api doesn't return any information. Will have to query parent folder""" 189 if not parent_id: 190 raise ValueError("Must pass a parent folder id: parent_id=None") 191 192 token = self._get_token(token) 193 data = { 194 "contentsId": ",".join(content_ids), 195 "folderIdDest": parent_id, 196 "token": token 197 } 198 199 resp = requests.put(GofileClient.API_ROUTE_COPY_CONTENT_URL, data=data) 200 got = GofileClient.handle_response(resp) 201 202 """ 203 As of right now /copyContent does not return information about newly created content 204 For this reason copy_content will just return None 205 206 return GofileContent.__init_from_resp__(resp, client=self) 207 """
Copy provided content_ids to destination folder's content_id. Currently returns None because api doesn't return any information. Will have to query parent folder
209 def create_folder(self, name: str, parent_id: str, token: str = None): 210 """Creates folder in specified parent folder's content_id""" 211 token = self._get_token(token) 212 213 data = { 214 "parentFolderId": parent_id, 215 "folderName": name 216 } 217 218 data["token"] = token 219 220 resp = requests.put(GofileClient.API_ROUTE_CREATE_FOLDER_URL, data=data) 221 got = GofileClient.handle_response(resp) 222 223 return GofileContent.__init_from_resp__(resp, client=self)
Creates folder in specified parent folder's content_id
277class GofileContent (object): 278 name: str 279 """Name of content""" 280 content_id: str 281 """Gofile API's unique content id""" 282 parent_id: str 283 """Content_id of parent folder""" 284 _type: str 285 """GofileContent subtypes, either 'file', 'folder' or 'unknown'.""" 286 is_file_type: bool 287 """If GofileContent is a file""" 288 is_folder_type: bool 289 """If GofileContent is a folder""" 290 is_unknown_type: bool 291 """If GofileContent is unknown (call reload() to update)""" 292 is_deleted: bool 293 """If content is deleted (will only register if called by it's own method delete())""" 294 295 def __init__(self, content_id: str, parent_id: str, _type: str = None, client: GofileClient = None): 296 self.content_id = content_id 297 self.parent_id = parent_id 298 self._type = _type 299 self._client = client 300 self._raw = {} 301 302 self.is_file_type = _type == "file" 303 self.is_folder_type = _type == "folder" 304 self.is_unknown_type = _type == None 305 self.name = None 306 self.time_created = None 307 self.is_deleted = False 308 309 def __repr__ (self) -> str: 310 _type = self._type 311 if not _type: 312 _type = "Unknown" 313 314 return "<Gofile {}: content_id={} name={}>".format(_type.upper(), self.content_id, self.name) 315 316 def delete (self) -> None: 317 """Deletes itself. When called successfully is_deleted = True""" 318 guest_token = self._raw.get("guestToken") 319 self._client.delete(self.content_id, token=guest_token) 320 self.is_deleted = True 321 322 def copy_to (self, dest_id: str) -> None: 323 """Copies itself to destination folder's content_id""" 324 self._client.copy_content(self.content_id, parent_id=dest_id) 325 326 def copy (self, dest_id: str) -> None: 327 self.copy_to(dest_id) 328 329 def set_option(self, option: str, value, reload: bool = True) -> None: 330 """Sets options for itself. Full option list available at gofile.io/api""" 331 self._client.set_content_option(self.content_id, option, value) 332 if reload: 333 self.reload() #reload to get up to date information 334 335 def reload (self): 336 """Reloads any new updates to content. If is_unknown_type = True then reload() returns updated content""" 337 if self.is_folder_type or (self.is_unknown_type and self.parent_id == None): 338 resp, data = self._client._get_content_raw_resp(self.content_id) 339 340 if self.is_unknown_type: 341 content = GofileContent.__init_from_resp__(resp, client=self._client) 342 343 elif self.is_folder_type: 344 self._override_from_dict(data) 345 return self 346 347 elif (self.is_unknown_type or self.is_file_type) and self.parent_id: 348 resp, data = self._client._get_content_raw_resp(self.parent_id) 349 content_data = data["contents"].get(self.content_id, None) 350 content = None 351 if content_data: 352 content = GofileContent.__init_from_resp__({"data": content_data}, client=self._client) 353 354 if self.is_file_type: 355 self._override_from_dict(content_data) 356 357 return content 358 359 else: 360 raise NotImplemented 361 362 @staticmethod 363 def __init_from_resp__ (resp: requests.Response, _type: str = None, client: GofileClient = None): 364 if type(resp) == requests.models.Response: 365 resp = resp.json() 366 367 got = resp["data"] 368 _type = got.get("type", _type) 369 content = None 370 371 if _type == "file": 372 content = GofileFile._load_from_dict(got, client=client) 373 elif _type == "folder": 374 content = GofileFolder._load_from_dict(got, client=client) 375 else: 376 raise NotImplemented 377 378 return content
295 def __init__(self, content_id: str, parent_id: str, _type: str = None, client: GofileClient = None): 296 self.content_id = content_id 297 self.parent_id = parent_id 298 self._type = _type 299 self._client = client 300 self._raw = {} 301 302 self.is_file_type = _type == "file" 303 self.is_folder_type = _type == "folder" 304 self.is_unknown_type = _type == None 305 self.name = None 306 self.time_created = None 307 self.is_deleted = False
316 def delete (self) -> None: 317 """Deletes itself. When called successfully is_deleted = True""" 318 guest_token = self._raw.get("guestToken") 319 self._client.delete(self.content_id, token=guest_token) 320 self.is_deleted = True
Deletes itself. When called successfully is_deleted = True
322 def copy_to (self, dest_id: str) -> None: 323 """Copies itself to destination folder's content_id""" 324 self._client.copy_content(self.content_id, parent_id=dest_id)
Copies itself to destination folder's content_id
329 def set_option(self, option: str, value, reload: bool = True) -> None: 330 """Sets options for itself. Full option list available at gofile.io/api""" 331 self._client.set_content_option(self.content_id, option, value) 332 if reload: 333 self.reload() #reload to get up to date information
Sets options for itself. Full option list available at gofile.io/api
335 def reload (self): 336 """Reloads any new updates to content. If is_unknown_type = True then reload() returns updated content""" 337 if self.is_folder_type or (self.is_unknown_type and self.parent_id == None): 338 resp, data = self._client._get_content_raw_resp(self.content_id) 339 340 if self.is_unknown_type: 341 content = GofileContent.__init_from_resp__(resp, client=self._client) 342 343 elif self.is_folder_type: 344 self._override_from_dict(data) 345 return self 346 347 elif (self.is_unknown_type or self.is_file_type) and self.parent_id: 348 resp, data = self._client._get_content_raw_resp(self.parent_id) 349 content_data = data["contents"].get(self.content_id, None) 350 content = None 351 if content_data: 352 content = GofileContent.__init_from_resp__({"data": content_data}, client=self._client) 353 354 if self.is_file_type: 355 self._override_from_dict(content_data) 356 357 return content 358 359 else: 360 raise NotImplemented
Reloads any new updates to content. If is_unknown_type = True then reload() returns updated content