Created
February 1, 2018 09:09
-
-
Save zrzka/b61c74975c777a77232035a3e171337d to your computer and use it in GitHub Desktop.
Imgur Upload
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!python3 | |
import base64 | |
import json | |
import appex | |
import clipboard | |
import objc_util | |
import photos | |
import requests | |
# | |
# https://api.imgur.com/oauth2/addclient | |
# | |
# Select Anonymous usage without user authorization | |
# | |
# Authorization callback URL is mandatory even if it's not used, you | |
# have to fill in anything, https://callback/ works :) | |
# | |
IMGUR_CLIENT_ID = '' | |
IMGUR_API = 'https://api.imgur.com/3' | |
class ImgurError(Exception): | |
pass | |
@objc_util.on_main_thread # workaround for https://github.com/omz/Pythonista-Issues/issues/518 | |
def pick_assets(): | |
screenshots = photos.get_screenshots_album() | |
return photos.pick_asset(assets=screenshots, multi=True) | |
class ImgurAsset: | |
""" | |
Args: | |
asset (`photos.Asset`, `bytes`): Asset you would like to upload | |
""" | |
def __init__(self, asset): | |
self.asset = asset if isinstance(asset, photos.Asset) else None | |
self.bytes = asset if isinstance(asset, bytes) else None | |
if not self.asset and not self.bytes: | |
raise ValueError('Invalid asset value, pass photos.Asset or bytes') | |
self.link = None | |
self.delete_hash = None | |
@classmethod | |
def headers(cls): | |
return dict(Authorization=f'Client-ID {IMGUR_CLIENT_ID}') | |
def upload(self): | |
data = self.asset.get_image_data().getvalue() if self.asset else self.bytes | |
headers = self.headers() | |
payload = dict(image=base64.b64encode(data).decode()) | |
response = requests.post(f'{IMGUR_API}/image', headers=headers, data=payload) | |
if not response.ok: | |
raise ImgurError('Failed to upload image') | |
j = json.loads(response.text) | |
if not j['success'] or not j['status'] == 200: | |
raise ImgurError('Failed to upload image') | |
self.link = j['data']['link'] | |
self.delete_hash = j['data']['deletehash'] | |
def delete(self): | |
if not self.delete_hash: | |
return | |
headers = self.headers() | |
response = requests.delete(f'{IMGUR_API}/image/{self.delete_hash}', headers=headers) | |
if not response.ok: | |
raise ImgurError(f'Failed to delete image {self.delete_hash}') | |
j = json.loads(response.text) | |
if not j['success'] or not j['status'] == 200: | |
raise ImgurError(f'Failed to delete image {self.delete_hash}') | |
self.link = None | |
self.delete_hash = None | |
def main(): | |
if appex.is_running_extension(): | |
assets = appex.get_images_data() | |
else: | |
assets = pick_assets() | |
if not assets: | |
print('No assets selected') | |
return | |
print(f'{len(assets)} asset(s) selected for upload') | |
imgur_assets = [ImgurAsset(x) for x in assets] | |
try: | |
for i, x in enumerate(imgur_assets): | |
print(f'Uploading {i+1}. asset') | |
x.upload() | |
except ImgurError as e: | |
print(e) | |
print('Upload failed, deleting already uploaded assets') | |
for x in imgur_assets: | |
try: | |
x.delete() | |
except Exception: | |
pass | |
else: | |
result = '\n'.join([ | |
f'![]({x.link})' | |
for x in imgur_assets | |
if x.link | |
]) | |
print(f'Asset links:\n{result}') | |
clipboard.set(result) | |
print('Asset links copied to the clipboard') | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment