├── tests ├── test_all.py └── __init__.py ├── pygofile ├── __init__.py └── gofile.py ├── LICENSE ├── README.md ├── setup.py └── .gitignore /tests/test_all.py: -------------------------------------------------------------------------------- 1 | from pygofile import Gofile 2 | 3 | gofile = Gofile(token='') -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | pygofile 3 | ~~~~~~~~~ 4 | 5 | :copyright: (c) 2021 by Gautam Kumar . 6 | 7 | 8 | :license: MIT, see LICENSE for more details. 9 | 10 | 11 | :description: Asyncronous Python Wrapper for the GoFile API 12 | """ -------------------------------------------------------------------------------- /pygofile/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | pygofile 3 | ~~~~~~~~~ 4 | 5 | :copyright: (c) 2021 by Gautam Kumar . 6 | 7 | 8 | :license: MIT, see LICENSE for more details. 9 | 10 | 11 | :description: Asynchronous Python Wrapper for the GoFile API 12 | """ 13 | 14 | __title__ = "pygofile" 15 | __author__ = "https://github.com/gautamajay52" 16 | __copyright__ = "Copyright 2021 " 17 | __license__ = "MIT" 18 | 19 | __version__ = "1.0.2" 20 | 21 | from .gofile import Gofile 22 | 23 | __all__ = ["Gofile"] 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 GautamKumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pygofile [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fgautamajay52%2Fpygofile&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://github.com/gautamajay52/pygofile) 2 | 3 | > Asynchronous Python Wrapper for the GoFile API (Unofficial). 4 | 5 | ### Installation : 6 | ```bash 7 | pip3 install pygofile 8 | ``` 9 | 10 | ### Usage : 11 | ```python 12 | >> from pygofile import Gofile 13 | 14 | >> gofile = Gofile(token='') # is your GoFile token 15 | 16 | # or 17 | 18 | >> gofile = Gofile() # as a guest 19 | 20 | # to upload 21 | >> data = await gofile.upload(file='/path/to/file.ext') 22 | 23 | >> print(data) 24 | {'downloadPage': 'https://gofile.io/d/OF8ctM', 'code': 'OF8ctM', 'parentFolder': '7a5cd11e-6fa34dda-44-bab5-c57d74d28d', 'fileId': 'e72b3dab-9190-48a0-9abe-89e45d1c0', 'fileName': 'file.ext', 'md5': '0aff68c0c302e07a52f4a1fbc5a687b', 'directLink': 'https://srv-store5.gofile.io/download/e72b3ab-9abe-8901c45d1c0/file.ext', 'info': 'Direct links only work if your account is a donor account. Standard accounts will have their links redirected to the download page.'} 25 | 26 | >> download_url = data['downloadPage'] 27 | 28 | >> await gofile.delete_content(content_id='e72b3dab-9190-48a0-9abe-89e45d1c0') 29 | ``` 30 | ### Credits: ⚡ 31 | * [GautamKumar(me)](https://github.com/gautamajay52) for [Nothing](https://github.com/gautamajay52/pygofile) -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """ 2 | pygofile 3 | ~~~~~~~~~ 4 | 5 | :copyright: (c) 2021 by Gautam Kumar . 6 | 7 | 8 | :license: MIT, see LICENSE for more details. 9 | 10 | 11 | :description: Asynchronous Python Wrapper for the GoFile API 12 | """ 13 | 14 | from setuptools import find_packages, setup 15 | 16 | AUTHOR = "gautamajay52" 17 | EMAIL = "gautamajay52@gmail.com" 18 | URL = "https://github.com/gautamajay52/pygofile" 19 | VERSION = "1.0.2" 20 | 21 | 22 | with open("README.md", "r", encoding="utf-8") as fh: 23 | long_description = fh.read() 24 | 25 | setup( 26 | name="pygofile", 27 | version=VERSION, 28 | description="Asynchronous Python Wrapper for the GoFile API", 29 | long_description=long_description, 30 | long_description_content_type="text/markdown", 31 | author=AUTHOR, 32 | author_email=EMAIL, 33 | url=URL, 34 | license="MIT", 35 | packages=find_packages(), 36 | keywords="API fileuploader storage python", 37 | project_urls={ 38 | "Source": "https://github.com/gautamajay52/pygofile", 39 | "Documentation": "https://github.com/gautamajay52/pygofile#readme", 40 | "Tracker": "https://github.com/gautamajay52/pygofile/issues", 41 | }, 42 | classifiers=[ 43 | "Development Status :: 5 - Production/Stable", 44 | "Intended Audience :: Developers", 45 | "License :: OSI Approved :: MIT License", 46 | "Operating System :: OS Independent", 47 | "Programming Language :: Python :: 3.6", 48 | "Programming Language :: Python :: 3.7", 49 | "Programming Language :: Python :: 3.8", 50 | "Programming Language :: Python :: 3.9", 51 | "Topic :: Internet", 52 | ], 53 | python_requires=">=3.6", 54 | install_requires=["aiohttp"], 55 | ) 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .nox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | .hypothesis/ 49 | .pytest_cache/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | db.sqlite3 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # IPython 77 | profile_default/ 78 | ipython_config.py 79 | 80 | # pyenv 81 | .python-version 82 | 83 | # celery beat schedule file 84 | celerybeat-schedule 85 | 86 | # SageMath parsed files 87 | *.sage.py 88 | 89 | # Environments 90 | .env 91 | .venv 92 | env/ 93 | venv/ 94 | ENV/ 95 | env.bak/ 96 | venv.bak/ 97 | 98 | # Spyder project settings 99 | .spyderproject 100 | .spyproject 101 | 102 | # Rope project settings 103 | .ropeproject 104 | 105 | # mkdocs documentation 106 | /site 107 | 108 | # mypy 109 | .mypy_cache/ 110 | .dmypy.json 111 | dmypy.json 112 | 113 | # Pyre type checker 114 | .pyre/ 115 | -------------------------------------------------------------------------------- /pygofile/gofile.py: -------------------------------------------------------------------------------- 1 | """ 2 | pygofile 3 | ~~~~~~~~~ 4 | 5 | MIT License 6 | 7 | Copyright (c) 2021 GautamKumar 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | 27 | """ 28 | 29 | import datetime 30 | import os 31 | from typing import Any, Dict 32 | from urllib.parse import urljoin 33 | 34 | from aiohttp import ClientSession 35 | 36 | __author__ = "https://github.com/gautamajay52" 37 | 38 | 39 | class NotAuthenticated(Exception): 40 | pass 41 | 42 | 43 | class ServerError(Exception): 44 | pass 45 | 46 | 47 | class Gofile: 48 | """ 49 | Base class for all methods of Gofile API. 50 | 51 | Parameters: 52 | token (`str`, optional ): 53 | Gofile API token. 54 | The access token of an account. Can be retrieved from the profile page. 55 | 56 | if set, your account wil be used else a guest account will be created. 57 | """ 58 | 59 | API: str = "https://{server}.gofile.io/" 60 | session = ClientSession 61 | 62 | def __init__(self, token=None) -> None: 63 | self.token = token 64 | 65 | async def upload( 66 | self, 67 | file: str, 68 | description: str = "", 69 | password: str = "", 70 | tags: str = "", 71 | expire: str = "", 72 | folder_id: str = "", 73 | ) -> Dict[str, str]: 74 | """ 75 | Upload one file on a specific server. 76 | If you specify a folder_id, the file will be added to this folder. 77 | 78 | Parameters: 79 | file (``str``, optional ): 80 | Must contain one file. 81 | If you want to upload multiple files, 82 | call uploadFile again and specify the folderId of the first file uploaded. 83 | 84 | token (``str``, optional ): 85 | The access token of an account. Can be retrieved from the profile page. 86 | If valid, the file will be added to this account. 87 | 88 | If undefined, a guest account will be created to receive the file. 89 | 90 | folder_id (``str``, optional ): 91 | The ID of a folder. 92 | If valid, the file will be added to this folder. 93 | If undefined, a new folder will be created to receive the file. 94 | 95 | When using the folderId, you must pass the account token. 96 | 97 | description (``str``, optional ): 98 | If valid, will set a description for the newly created folder. 99 | Markdown syntax can be used. 100 | 101 | Not applicable if you specify a folderId. 102 | 103 | password (``str``, optional ): 104 | If valid, will set a password for the newly created folder. 105 | min length of password is 4 106 | 107 | Not applicable if you specify a folderId. 108 | 109 | tags (``str``, optional ): 110 | If valid, will set tags for the newly created folder. 111 | If multiple tags, seperate them with comma (`example` : `"tags1,tags2"`) 112 | 113 | Not applicable if you specify a folderId. 114 | 115 | expire (``str``, optional ): 116 | If valid, will set an expiration date for the newly created folder. 117 | Must be in the form of unix timestamp. (`Format`: `yyyy-mm-dd``) 118 | 119 | Not applicable if you specify a folderId. 120 | 121 | """ 122 | if not os.path.isfile(file): 123 | raise ValueError("Only file supported") 124 | elif password and len(str(password)) < 4: 125 | raise ValueError("password is too short (min len 4)") 126 | 127 | data_ = self.serialize( 128 | file=file, 129 | description=description, 130 | password=password, 131 | tags=tags, 132 | expire=expire, 133 | folder_id=folder_id, 134 | ) 135 | 136 | if self.token: 137 | data_["token"] = self.token 138 | 139 | async with self.session() as session: 140 | with open(file, "rb") as _file: 141 | data_["file"] = _file 142 | server = await self.server(session) 143 | url = urljoin(self.API.format(server=server), "uploadFile") 144 | data = await session.post(url, data=data_) 145 | return self.parse_json(await data.json()) 146 | 147 | async def get_account_details(self, all_details=False) -> Dict[str, str]: 148 | """ 149 | Retrieving specific account information 150 | 151 | Parameters: 152 | all_details (`bool` , optional ): 153 | If set, all details will be returned. 154 | 155 | If undefined, minimal information will be returned. 156 | """ 157 | if not self.token: 158 | raise NotAuthenticated("You must provide token.") 159 | 160 | params = {"token": self.token} 161 | if all_details: 162 | params["allDetails"] = 'true' 163 | 164 | async with self.session() as session: 165 | url = urljoin( 166 | self.API.format(server="api"), 167 | "getAccountDetails", 168 | ) 169 | data = await session.get( 170 | url, params=params, 171 | ) 172 | return self.parse_json(await data.json()) 173 | 174 | async def delete_content(self, content_id: str) -> Dict[str, str]: 175 | """ 176 | Delete file or folder 177 | 178 | Parameters: 179 | content_id (``str``): 180 | The file or folder ID. 181 | """ 182 | if not self.token: 183 | raise NotAuthenticated("You must provide token.") 184 | async with self.session() as session: 185 | data = {"contentId": content_id, "token": self.token} 186 | url = urljoin(self.API.format(server="api"), "deleteContent") 187 | data = await session.delete(url, data=data) 188 | return self.parse_json(await data.json()) 189 | 190 | async def set_folder_options( 191 | self, folder_id: str, option: str, value: str 192 | ) -> Dict[str, str]: 193 | """ 194 | Set an option on a folder 195 | 196 | Parameters: 197 | folder_id (``str``): 198 | The folder ID. 199 | 200 | option (``str``): 201 | Can be "private", "password", "description", "expire" or "tags". 202 | 203 | value (``str``): 204 | The value of the option to be defined. 205 | 206 | For "private", can be "true" or "false". 207 | 208 | For "password", must be the password. (``Min len 4``) 209 | 210 | For "description", must be the description. 211 | 212 | For "expire", must be the expiration date in the form of unix timestamp (`Format`: `yyyy-mm-dd``). 213 | 214 | For "tags", must be a comma seperated list of tags. 215 | 216 | You can have only one option and value at a time. 217 | """ 218 | if not self.token: 219 | raise NotAuthenticated("You must provide token.") 220 | async with self.session() as session: 221 | data = { 222 | "token": self.token, 223 | "folderId": folder_id, 224 | "option": option, 225 | "value": str(value).replace(" ", "") if option == "tags" else value, 226 | } 227 | url = urljoin(self.API.format(server="api"), "setFolderOptions") 228 | data = await session.put(url, data=data) 229 | data = await data.json() 230 | return self.parse_json(data) 231 | 232 | async def create_folder( 233 | self, parent_folder_id: str, folder_name: str 234 | ) -> Dict[str, str]: 235 | """ 236 | Create a new folder 237 | 238 | Parameters: 239 | parent_folder_id (``str``): 240 | The parent folder ID. 241 | 242 | folder_name (``str``): 243 | The name of the created folder. 244 | """ 245 | if not self.token: 246 | raise NotAuthenticated("You must provide token.") 247 | 248 | async with self.session() as session: 249 | data = { 250 | "token": self.token, 251 | "folderName": folder_name, 252 | "parentFolderId": parent_folder_id, 253 | } 254 | url = urljoin(self.API.format(server="api"), "createFolder") 255 | data = await session.put(url, data=data) 256 | data = await data.json() 257 | return self.parse_json(data) 258 | 259 | async def server(self, session: ClientSession) -> Dict[str, str]: 260 | """ 261 | To get server name form Gofile API 262 | """ 263 | url = urljoin(self.API.format(server="api"), "getServer") 264 | server = await (await session.get(url)).json() 265 | server = self.parse_json(server) 266 | return server["server"] 267 | 268 | @staticmethod 269 | def serialize(**kwargs) -> Dict[str, str]: 270 | """ 271 | Just to parse input values to a dict 272 | """ 273 | data = {} 274 | for k, v in kwargs.items(): 275 | if k == "folder_id" and v: 276 | data = {} 277 | data["folderId"] = v 278 | return data 279 | elif k == "description" and v: 280 | data[k] = str(v) 281 | elif k == "password" and v: 282 | data[k] = str(v) 283 | elif k == "tags" and v: 284 | data[k] = str(v).replace(" ", "") 285 | elif k == "expire" and v: 286 | year, mon, day = (int(a) for a in str(v).split("-")) 287 | timestamp = datetime.datetime(year, mon, day).timestamp() 288 | data[k] = str(timestamp).split(".", maxsplit=1)[0] 289 | return data 290 | 291 | @staticmethod 292 | def parse_json(json_) -> Dict[str, str]: 293 | """ 294 | parse final json and send data as dict 295 | """ 296 | if json_["status"] == "ok": 297 | return json_["data"] 298 | raise ServerError(json_["status"]) 299 | --------------------------------------------------------------------------------