fixing renderText script

This commit is contained in:
2026-06-11 15:14:00 +02:00
parent 3e922883f7
commit 9ad6b15130
302 changed files with 120914 additions and 20 deletions
Executable
+512
View File
@@ -0,0 +1,512 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import urllib2
import json
from base64 import b64encode
from getpass import getpass
from urllib import urlencode
from cookielib import CookieJar
from os.path import expanduser, exists
from pprint import pprint
from collections import OrderedDict
from argparse import ArgumentParser
USERNAME = "rbotara"
PASSWORD = "cigareta"
APIKEY_AUTH = "acfe292a432ded08e576f019fb4e34d104df16436"
APIKEY_ANON = "641ff5860e0a7e26e97e48d8ee80d162"
DEBUG = False
class ImgurError(Exception):
pass
class Imgur(object):
"""
This class can be used to upload images and manage an account on imgur.com
"""
base = "api.imgur.com"
connected = False
urls = {
# Anon
"upload": "/2/upload",
"image": "/2/image/%s",
"delete": "/2/delete/%s",
# Auth
"signin": "/2/signin",
"account": "/2/account",
"account_images": "/2/account/images",
"account_image": "/2/account/images/%s",
"account_images_count": "/2/account/images_count",
"albums": "/2/account/albums",
"album": "/2/account/albums/%s",
"albums_count": "/2/account/albums_count",
"albums_order": "/2/account/albums_order",
"album_order": "/2/account/albums_order/%s",
# Other
"stats": "/2/stats",
"credits": "/2/credits",
}
def __init__(self, apikey_auth=None, apikey_anon=None, print_results=True):
self.apikey_auth = apikey_auth
self.apikey_anon = apikey_anon
self.print_results = print_results
self.cj = CookieJar()
def _handle_response(fun):
def new_f(self, *args, **kwargs):
try:
resp = fun(self, *args, **kwargs)
except urllib2.HTTPError, err:
raise ImgurError(err)
else:
if self.print_results:
content = resp.read()
try:
#pprint(json.loads(content))
json_print(json.loads(content))
except:
pprint(content)
return resp
return new_f
def connection_required(fun):
""" A decorator that checks if the user is authenticated """
def new_f(self, *args, **kwargs):
if not self.connected:
raise ImgurError("You must be connected to perform this"
"operation")
return fun(self, *args, **kwargs)
return new_f
def connect(self, username=None, password=None):
"""
A cookie is created for the authentication
"""
response = self.request("POST", "signin",
username=username, password=password)
debug("Connected.")
self.connected = True
def _json(self, data):
try:
return json.loads(data)
except ValueError:
raise ImgurError("Invalid data")
@_handle_response
@connection_required
def _account(self):
return self.request("GET", "account")
@_handle_response
def _upload(self, filename, url, name, title, caption):
if filename:
with open(expanduser(filename), "rb") as f:
img = b64encode(f.read())
t = "base64"
else:
img = url
t = "url"
url = "account_images" if self.connected else "upload"
return self.request("POST", url, image=img,
type=t, name=name, title=title, caption=caption)
@_handle_response
@connection_required
def _imgedit(self, hash, title="", caption=""):
url = self.urls["account_image"] % hash
return self.request("POST", url=url, title=title, caption=caption)
@_handle_response
def _imginfos(self, hash):
c = self.connected
url = self.urls["account_image" if c else "image"] % hash
return self.request("GET", url=url)
@_handle_response
def _imgdelete(self, hash):
c = self.connected
url = self.urls["account_image" if c else "delete"] % hash
return self.request("DELETE", url=url)
@_handle_response
@connection_required
def _imgcount(self):
return self.request("GET", "account_images_count")
@_handle_response
@connection_required
def _list(self):
return self.request("GET", "account_images")
@_handle_response
@connection_required
def _albums(self, title="", description="", privacy="", layout="",
count="", page="", create=True):
if create:
return self.request("POST", "albums", title=title,
description=description, privacy=privacy, layout=layout)
else:
return self.request("GET", "albums", count=count, page=page)
@_handle_response
@connection_required
def _albmlist(self, album_id):
url = self.urls["album"] % album_id
return self.request("GET", url=url)
@_handle_response
@connection_required
def _albmdelete(self, album_id):
url = self.urls["album"] % album_id
return self.request("DELETE", url=url)
@_handle_response
@connection_required
def _albmedit(self, album_id, title="", description="", cover="",
privacy="", layout="", images="", add_images="", del_images=""):
url = self.urls["album"] % album_id
datas = {}
for k in ("url", "title", "description", "cover", "privacy", "layout",
"images", "add_images", "del_images"):
datas[k] = locals()[k]
return self.request("POST", **datas)
@_handle_response
@connection_required
def _albmcount(self):
return self.request("GET", "albums_count")
@_handle_response
@connection_required
def _albmord(self, album_id, hashes):
url = self.urls["album_order"] % album_id
return self.request("POST", url=url, hashes=hashes)
@_handle_response
@connection_required
def _albmords(self, album_ids):
return self.request("POST", "albums_order", album_ids=album_ids)
@_handle_response
def _limits(self):
return self.request("GET", "credits")
def _stats(self, view):
return self.request("GET", "stats", view=view)
def request(self, method, key="", url="", headers=None, **params):
# Send an http request.
# if key is set, use the url from self.urls[key]
# else use 'url'
if not headers:
headers = {}
url = "http://" + self.base + (self.urls[key] if key else url) + ".json"
params["key"] = self.apikey_auth if self.connected else self.apikey_anon
data = None
if method in ("POST", "DELETE"):
for k in params.keys():
if not params[k]:
del params[k]
data = urlencode(params)
elif method in ("GET", "DELETE"):
url = "%s?%s" % (url, urlencode(params))
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
urllib2.install_opener(opener)
debug(url, params)
req = urllib2.Request(url, data, headers)
if not method in ("POST", "GET"):
req.get_method = lambda: method
return urllib2.urlopen(req)
def _get_json(self, fun_name, *args, **kwargs):
return self._json(getattr(self, fun_name)(*args, **kwargs).read())
def _infos(self, img):
""" Print the infos of an image """
return dict_print(OrderedDict(img["image"].items() +
img["links"].items()))
def _liststr(self, datas):
""" Converts a list into "(foo,bar,baz)" """
if isinstance(datas, (list, tuple)):
datas = "(%s)" % (",".join(str(e) for e in datas))
elif not datas.startswith("("):
datas = "(%s)" % datas
return datas
def upload_image(self, image="", name="", title="", caption="", hashes=False):
"""
Upload an image
'image' can be a path or an url
if hashes is True, return only the hashes
"""
url, file = "", ""
if not exists(image):
url = image
else:
file = image
datas = self._get_json("_upload", file, url, name, title, caption)
infos = datas["images" if self.connected else "upload"]
if hashes:
return "Hash: %s\nDelete: %s" % (infos["image"]["hash"],
infos["image"]["deletehash"])
else:
return self._infos(infos)
def account(self):
""" Get account infos """
datas = self._get_json("_account")
return dict_print(datas["account"])
def list_images(self):
""" List all images in account """
datas = self._get_json("_list")
imgs = (self._infos(img) for img in datas["images"])
return "\n *** \n".join(imgs)
def infos_image(self, hash):
""" Retrieve informations from an image """
datas = self._get_json("_imginfos", hash)
return self._infos(datas["images" if self.connected else "image"])
def delete_image(self, hash):
""" Delete an image """
datas = self._get_json("_imgdelete", hash)
return datas["images"]["message"] if self.connected else ""
def edit_image(self, hash, new_title="", new_caption=""):
""" Edit an image """
datas = self._get_json("_imgedit", hash, new_title, new_caption)
return self._infos(datas["images"])
def count_images(self):
""" Count all images in the account """
return self._get_json("_imgcount")["images_count"]["count"]
def list_albums(self, count=30, page=1):
"""
List all albums in the account
"""
datas = self._get_json("_albums", count=count, page=page,
create=False)
return "\n *** \n".join(dict_print(alb) for alb in datas["albums"])
def create_album(self, title="", description="", privacy="", layout=""):
"""
All values are optional.
privacy: public/hidden/secret
layout: blog/horizontal/vertical/grid
"""
datas = self._get_json("_albums", title, description, privacy, layout)
return dict_print(datas["albums"])
def list_album(self, album_id):
""" List all images in an album """
datas = self._get_json("_albmlist", album_id)
imgs = (self._infos(img) for img in datas["albums"])
return "\n *** \n".join(imgs)
def delete_album(self, album_id):
""" Delete an album """
datas = self._get_json("_albmdelete", album_id)
return datas["albums"]["message"]
def edit_album(self, album_id, title="", description="", cover="",
privacy="", layout="", images="", add_images="", del_images=""):
"""
Edit an album
privacy: public/hidden/secret
layout: blog/horizontal/vertical/grid
cover: a hash of an image in the account
'images' replaces all images in the album
images, add_images and del_images must be a list of hashes,
or a string formatted like (hash1,hash2,...)
"""
for k in ("images", "add_images", "del_images"):
locals()[k] = self._liststr(locals()[k])
datas = self._get_json("_albmedit", album_id, title, description,
cover, privacy, layout, images, add_images, del_images)
imgs = (self._infos(img) for img in datas["albums"])
return "\n *** \n".join(imgs)
def count_albums(self):
""" Return the number of albums. """
datas = self._get_json("_albmcount")
return datas["albums_count"]["count"]
def order_album(self, album_id, hashes):
hashes = self._liststr(hashes)
datas = self._get_json("_albmord", album_id, hashes)
return "\n *** \n".join(dict_print(alb) for alb in datas["albums_order"])
def order_albums(self, album_ids):
album_ids = self._liststr(album_ids)
datas = self._get_json("_albmords", album_ids)
imgs = (self._infos(img) for img in datas["albums_order"])
return "\n *** \n".join(imgs)
def stats(self, view="month"):
"""
View imgur's stats
view: today|week|month
"""
return dict_print(self._get_json("_stats", view)["stats"])
def debug(*datas):
if DEBUG:
print "DEBUG:", ", ".join(str(d) for d in datas)
def json_print(data, tab=0):
if isinstance(data, (list, tuple)):
print
for elem in data:
json_print(elem, tab)
print
elif isinstance(data, dict):
print
for e, d in data.items():
print "\t"*tab, e,
json_print(d, tab+1)
else:
print "\t"*tab, data
def dict_print(data):
def align(l, r, w=80):
return "%s: %s%s" % (l, (w-len(l))* " ", r)
w = max(len(e) for e in data.keys())
return "\n".join(align(k, v, w) for k, v in data.items())
def main():
i = Imgur(APIKEY_AUTH, APIKEY_ANON, False)
# Parser definition
parser = ArgumentParser(description="A command-line utility for imgur.com")
parser.add_argument("--user")
parser.add_argument("--password")
parser.add_argument("--ask-pass", action="store_true",
help="Prompt for a password, so that it will never be displayed.")
parser.add_argument("--anon", action="store_true", default=False,
help="Do not authenticate.")
sparsers = parser.add_subparsers(metavar="ACTION", dest='sp_name',
help="Use '%(prog)s action -h' for more help")
up_parser = sparsers.add_parser("upload", help="Upload a file or an url")
up_parser.add_argument("image", help="A path or an url")
up_parser.add_argument("-t", "--title")
up_parser.add_argument("-n", "--name")
up_parser.add_argument("-c", "--caption")
up_parser.add_argument("-s", "--hashes", action="store_true",
help="Only print the hashes instead of all the informations")
imgd_parser = sparsers.add_parser("delete", help="Delete an image")
imgd_parser.add_argument("hash")
imgi_parser = sparsers.add_parser("infos", help="Get infos on the image")
imgi_parser.add_argument("hash")
imge_parser = sparsers.add_parser("edit", help="Edit an image")
imge_parser.add_argument("hash")
imge_parser.add_argument("-t", "--title")
imge_parser.add_argument("-c", "--caption")
list_parser = sparsers.add_parser("list", help="List all your images")
acc_parser = sparsers.add_parser("account", help="Account infos")
albc_parser = sparsers.add_parser("create-album", help="Create a new album")
albc_parser.add_argument("-t", "--title")
albc_parser.add_argument("-d", "--description")
albc_parser.add_argument("-p", "--privacy", choices=["public", "hidden",
"secret"])
albc_parser.add_argument("-l", "--layout", choices=["blog", "horizontal",
"vertical", "grid"])
albe_parser = sparsers.add_parser("edit-album", help="Edit an album")
albe_parser.add_argument("album_id")
albe_parser.add_argument("-t", "--title")
albe_parser.add_argument("-d", "--description")
albe_parser.add_argument("-p", "--privacy", choices=["public", "hidden",
"secret"])
albe_parser.add_argument("-l", "--layout", choices=["blog", "horizontal",
"vertical", "grid"])
albe_parser.add_argument("-c", "--cover", help="The hash of an image to use "
"as cover for the album", metavar="hash")
albe_parser.add_argument("-i", "--images", metavar="hash1,hash2,..,hashN",
help="Replace all images in an album.")
albe_parser.add_argument("-a", "--add", metavar="hash1,hash2,..,hashN",
help="Add images to the album.")
albe_parser.add_argument("-r", "--delete", metavar="hash1,hash2,..,hashN",
help="Delete images from the album.")
albl_parser = sparsers.add_parser("list-albums",
help="List all albums.")
albl_parser.add_argument("-c", "--count", help="The number of albums to return")
albl_parser.add_argument("-p", "--page", help="The pages of albums to return")
albs_parser = sparsers.add_parser("list-album",
help="List all images in an album")
albs_parser.add_argument("album_id")
albco_parser = sparsers.add_parser("count-albums",
help="Get the number of albums")
albd_parser = sparsers.add_parser("delete-album", help="Delete an album")
albd_parser.add_argument("album_id")
albos_parser = sparsers.add_parser("order-albums", help="Order all albums in the account")
albos_parser.add_argument("album_ids", metavar="id1,id2,...,idn", help="The new list of album IDs")
albo_parser = sparsers.add_parser("order-album", help="Order all images in an album")
albo_parser.add_argument("album_id")
albo_parser.add_argument("hashes", metavar="hash1,hash2,...,hashn", help="The new list of hashes")
stats_parser = sparsers.add_parser("stats", help="Imgur statistics")
stats_parser.add_argument("-v", "--view",
choices=["today", "month", "week"])
# Authentification
args = parser.parse_args()
u, p, ap = args.user, args.password, args.ask_pass
if u and not p:
if ap:
i.connect(u, getpass())
else:
i.connect(u, PASSWORD)
elif p and not u:
i.connect(USERNAME, p)
elif u and p:
i.connect(u, p)
elif USERNAME and (not PASSWORD or ap) and not args.anon:
i.connect(USERNAME, getpass())
elif USERNAME and PASSWORD and not args.anon:
i.connect(USERNAME, PASSWORD)
# Preparation
opts = vars(args)
spname = args.sp_name
del opts["user"], opts["password"], opts["anon"], opts["ask_pass"]
if spname in ("upload", "infos", "delete", "edit", "list", "count"):
fun_name = spname + "_image" if hasattr(Imgur,
spname + "_image") else spname + "_images"
elif spname.rstrip("s").endswith("album"):
fun_name = spname.replace("-", "_")
else:
fun_name = spname
del opts["sp_name"]
fun = getattr(Imgur, fun_name)
# And action.
print fun(i, **opts)
if __name__ == "__main__":
main()