├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.rst ├── imgur_uploader.py ├── requirements.txt ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Project-specific 2 | .env 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *,cover 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | 56 | # Sphinx documentation 57 | docs/_build/ 58 | 59 | # PyBuilder 60 | target/ 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Andrew T. Baker 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 | 23 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst LICENSE requirements.txt -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | imgur-uploader 2 | ============== 3 | 4 | A simple command line client for uploading files to Imgur. 5 | 6 | Created for my `PyCon US 2015 Docker tutorial 7 | `_ so that students using 8 | my cloud servers can see the gifs they create at the end of exercise 1. 9 | 10 | This tool is open source under the `MIT License `_. 11 | 12 | Quickstart 13 | ---------- 14 | 15 | Getting Imgur API credentials 16 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 17 | 18 | Go to https://api.imgur.com/oauth2/addclient and register a new Imgur API 19 | client. You will need an Imgur account to do this. 20 | 21 | You can put it any valid URL for the callback URL - we won't be using it. 22 | 23 | Installing imgur-uploader 24 | ^^^^^^^^^^^^^^^^^^^^^^^^^ 25 | 26 | Installing imgur-uploader is easy. It runs on versions of Python >=2.7 or >=3.3. 27 | 28 | If you just want to use imgur-uploader, you can just ``pip install 29 | imgur-uploader``. 30 | 31 | If you want to tweak or enhance imgur-uploader, follow these instructions: 32 | 33 | #. Clone this repository 34 | #. Install the tool with ``pip install -e .`` 35 | 36 | Using imgur-uploader 37 | ^^^^^^^^^^^^^^^^^^^^ 38 | 39 | First, create a file called ``~/.config/imgur_uploader/uploader.cfg``, with the 40 | following contents (substitute your credentials):: 41 | 42 | [imgur] 43 | id = 9354da9ecdcfae3 44 | secret = 8387eca75687ecad9876ead47786edac0875dc0d 45 | 46 | Otherwise, set the ``IMGUR_API_ID`` and ``IMGUR_API_SECRET`` environment 47 | variables in your terminal session, using your client's credentials. 48 | 49 | Upload an image by running ``imgur-uploader path/to/my.gif`` 50 | 51 | The tool will return a shortened link to your uploaded gif upon completion:: 52 | 53 | Uploading file my.gif 54 | ... 55 | File uploaded - see your gif at http://i.imgur.com/6WsQPpw.gif 56 | 57 | If you want your images to appear in your account, you additionally need to 58 | get a refresh token. See the `Imgur API ` 59 | for information on how to obtain this. Then, add a ``refresh_token`` line in 60 | your config file:: 61 | 62 | [imgur] 63 | id = 9354da9ecdcfae3 64 | secret = 8387eca75687ecad9876ead47786edac0875dc0d 65 | refresh_token = 9812398ab1b2cc98de9fa982bacd31cb312c6194 66 | -------------------------------------------------------------------------------- /imgur_uploader.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import click 4 | from imgurpython import ImgurClient 5 | 6 | try: 7 | import ConfigParser 8 | except ImportError: 9 | import configparser as ConfigParser 10 | 11 | 12 | def get_config(): 13 | client_id = os.environ.get("IMGUR_API_ID") 14 | client_secret = os.environ.get("IMGUR_API_SECRET") 15 | refresh_token = os.environ.get("IMGUR_REFRESH_TOKEN") 16 | 17 | config = ConfigParser.ConfigParser() 18 | config.read([os.path.expanduser("~/.config/imgur_uploader/uploader.cfg")]) 19 | 20 | try: 21 | imgur = dict(config.items("imgur")) 22 | except: 23 | imgur = {} 24 | 25 | client_id = client_id or imgur.get("id") 26 | client_secret = client_secret or imgur.get("secret") 27 | refresh_token = refresh_token or imgur.get("refresh_token", "") 28 | 29 | if not (client_id and client_secret): 30 | return {} 31 | 32 | data = {"id": client_id, "secret": client_secret} 33 | if refresh_token: 34 | data["refresh_token"] = refresh_token 35 | return data 36 | 37 | 38 | @click.command() 39 | @click.argument("images", type=click.Path(exists=True), nargs=-1) 40 | def upload_image(images): 41 | """Uploads image files to Imgur""" 42 | 43 | config = get_config() 44 | 45 | if not config: 46 | click.echo( 47 | "Cannot upload - could not find IMGUR_API_ID or " "IMGUR_API_SECRET environment variables or config file" 48 | ) 49 | return 50 | 51 | if "refresh_token" in config: 52 | client = ImgurClient(config["id"], config["secret"], refresh_token=config["refresh_token"]) 53 | anon = False 54 | else: 55 | client = ImgurClient(config["id"], config["secret"]) 56 | anon = True 57 | 58 | links = [] 59 | copylink = True 60 | 61 | try: 62 | import pyperclip 63 | except ImportError: 64 | copylink = False 65 | 66 | for image in images: 67 | click.echo("Uploading file {}".format(click.format_filename(image))) 68 | 69 | response = client.upload_from_path(image, anon=anon) 70 | 71 | click.echo("File uploaded - see your image at {}".format(response["link"])) 72 | 73 | if copylink: 74 | # add individual link to clipboard 75 | links.append(response["link"]) 76 | pyperclip.copy(response["link"]) 77 | 78 | if copylink: 79 | # add all links to the clipboard 80 | # useful if user does not have a clipboard manager with history 81 | pyperclip.copy("\n".join(links)) 82 | else: 83 | print("pyperclip not found. To enable clipboard functionality, please install it.") 84 | 85 | 86 | if __name__ == "__main__": 87 | upload_image() 88 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | click==4.0 2 | imgurpython==1.1.5 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [wheel] 2 | universal = 1 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from setuptools import setup 4 | 5 | 6 | def read(*paths): 7 | """Build a file path from *paths* and return the contents.""" 8 | with open(os.path.join(*paths), 'r') as f: 9 | return f.read() 10 | 11 | setup( 12 | name='imgur-uploader', 13 | version='0.3.0', 14 | description='A simple command line client for uploading files to Imgur.', 15 | long_description=read('README.rst'), 16 | url='https://github.com/atbaker/imgur-uploader', 17 | license='MIT', 18 | author='Andrew Tork Baker', 19 | author_email='andrew@atbaker.me', 20 | py_modules=['imgur_uploader'], 21 | include_package_data=True, 22 | install_requires=[ 23 | 'click', 24 | 'pyperclip', 25 | 'imgurpython' 26 | ], 27 | entry_points=''' 28 | [console_scripts] 29 | imgur-uploader=imgur_uploader:upload_image 30 | imgur=imgur_uploader:upload_image 31 | ''', 32 | classifiers=[ 33 | 'Development Status :: 5 - Production/Stable', 34 | 'Intended Audience :: Developers', 35 | 'Natural Language :: English', 36 | 'License :: OSI Approved :: MIT License', 37 | 'Operating System :: OS Independent', 38 | 'Programming Language :: Python', 39 | 'Programming Language :: Python :: 2', 40 | 'Programming Language :: Python :: 2.7', 41 | 'Programming Language :: Python :: 3', 42 | 'Programming Language :: Python :: 3.3', 43 | 'Programming Language :: Python :: 3.4', 44 | 'Topic :: Utilities', 45 | ] 46 | ) 47 | --------------------------------------------------------------------------------