Skip to content

Instantly share code, notes, and snippets.

@mosquito
Created August 20, 2014 12:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mosquito/33d373630ab126e0ac85 to your computer and use it in GitHub Desktop.
Save mosquito/33d373630ab126e0ac85 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import os
import sys
import urllib2
import ConfigParser
import traceback
import base64
import tempfile
import json
from optparse import OptionParser
class Progress(object):
def __init__(self, title=''):
self._seen = 0.0
self._filename = title
def __call__(self, total, size, name, *args):
self._seen += size
sys.stdout.write('\r%s in progress: %3.2f%%' % (self._filename, (self._seen / total) * 100.0))
sys.stdout.flush()
class File(file):
def __init__(self, path, mode, callback=lambda x, y, z: (x, y, z)):
file.__init__(self, path, mode)
self.__total = os.stat(path).st_size
self.__callback = callback
self.__args = args
def __len__(self):
return self.__total
def read(self, size=2**15):
data = file.read(self, size)
self.__callback(self.__total, len(data), *self.__args)
return data
# curl -i --user api:YOUR_API_KEY --data-binary @large.png https://api.tinypng.com/shrink
def main(args, options):
top_level_url = options.url
for f in args:
if not os.path.exists(f):
print 'File "{0}" doesn\'t exists'.format(f)
exit(64)
name, ext = os.path.splitext(f)
if not ext.endswith('png'):
print 'File "{0}" not png file'.format(f)
exit(65)
for f in args:
print 'Shinking:'
with File(f, 'rb', Progress(' => "{0}"'.format(os.path.basename(f)))) as fd:
try:
request = urllib2.Request(top_level_url, fd)
size = os.stat(f).st_size
base64string = base64.encodestring('{0}:{1}'.format(options.username, options.api_key)).replace('\n', '')
request.add_header("Authorization", "Basic %s" % base64string)
result = urllib2.urlopen(request)
tmp_name = tempfile.NamedTemporaryFile(suffix='.png').name
result = json.load(result)
with open(tmp_name, 'w+') as tmp:
print '\n => Downloading "{0}"...'.format(result['output']['url'])
request = urllib2.Request(result['output']['url'])
response = urllib2.urlopen(request)
tmp.write(response.read())
new_size = os.stat(tmp_name).st_size
os.rename(f, "{0}.bak".format(f))
os.rename(tmp_name, f)
print " => Done shrinked {0} ({1}%)\n".format(
(result['input']['size'] - result['output']['size']), (1-result['output']['ratio']) * 100
)
if not options.backup:
os.remove("{0}.bak".format(f))
except urllib2.HTTPError as e:
print "\n => HTTP Error {0}: '{1}'".format(e.code, e.read())
return exit(1)
except Exception as e:
print traceback.format_exc()
raise e
if __name__ == '__main__':
parser = OptionParser(usage="usage: %prog [options] file1 [file2...[fileN]]")
parser.add_option("-K", "--key", dest="api_key",
help='API key for "http://tinypng.com"', metavar="KEY", default=None)
parser.add_option("-U", "--url", dest="url", help='URL address for "http://tinypng.com"',
metavar="URL", default="https://api.tinypng.com/shrink")
parser.add_option("-u", "--user", dest="username", help='Username for "http://tinypng.com"',
metavar="USERNAME", default="api")
parser.add_option("-B", "--backup", dest="backup", help='Backup original file',
action='store_true', default=False)
options, args = parser.parse_args()
config_file = os.path.join(os.path.expanduser('~'), '.pngshrinkrc')
config = ConfigParser.ConfigParser()
if os.path.exists(config_file):
config.read(config_file)
api_key = config.get('main', 'key')
options.api_key = api_key
else:
if options.api_key:
api_key = options.api_key
config.add_section('main')
config.set('main', 'key', api_key)
else:
print "You must set api key"
exit(128)
with open(config_file, 'w+') as f:
config.write(f)
main(args, options)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment