#!/usr/bin/env python3 # -*- encoding: utf-8 -*- import json import os import shutil import tkinter from concurrent.futures import ThreadPoolExecutor from io import BytesIO from pathlib import Path import filetype from PIL import Image, ImageTk class DownloadedData(object): def __init__(self, loadfrom=None): self.initialize() self.loadfrom(loadfrom) def initialize(self): self.control = list() self.fb = dict() def loadfrom(self, loadfrom): if loadfrom: with open(os.path.join(loadfrom, 'meta.json')) as f: self.control = json.loads(f.read()) for ctrl in self.control: fnm = ctrl['dname'] cnt = b'' with open(os.path.join(loadfrom, fnm), 'rb') as f: cnt = f.read() self.fb[fnm] = cnt def storedLinks(self): return [ctrl['link'] for ctrl in self.control] def put(self, link, downloaded, ext=None): global rootWindow if ext is None: try: ext = link.rsplit('/', 1)[-1].rsplit('.', 1)[-1] if ext not in ['jpg', 'png', 'gif', 'webp']: raise Exception except: ext = filetype.guess_extension(downloaded) if ext is None: ext = 'unk' fnm = '%04d.%s' % (len(self.control), ext) self.control.append({ 'dname': fnm, 'link': link, 'ext': ext, }) self.fb[fnm] = downloaded if userWantsPreview and rootWindow is None: rootWindow = MainApp() if rootWindow is not None and downloaded is not None: try: rootWindow.update_image(Image.open(BytesIO(downloaded)), link) except: pass if (pth := Path('latest_put_image.file')).exists(): pth.unlink() Path('latest_put_image.url').write_text(link) Path('latest_put_image.file').write_bytes(downloaded) def remove(self, directory): directory = os.path.abspath(directory) if os.path.exists(directory): shutil.rmtree(directory) def into(self, directory): self.remove(directory) directory = os.path.abspath(directory) os.makedirs(directory) try: with open(os.path.join(directory, 'meta.json'), 'w') as f: f.write(json.dumps(self.control, sort_keys=True, indent=2)) for seq, (fnm, dtb) in enumerate(self.fb.items()): with open(os.path.join(directory, fnm), 'wb') as f: f.write(dtb) print(' '*50, end='', flush=True) print('\r', end='', flush=True) print(f' `--> Saving image {seq+1} of {len(self.fb)}', end='', flush=True) print('\r', end='', flush=True) except KeyboardInterrupt as e: shutil.rmtree(directory) raise e def merge(self, other): for oitem in other.control: self.put(oitem['link'], other.fb[oitem['dname']], oitem['ext']) def bulk_merge(self, others): for other in others: self.merge(other) class MainApp(tkinter.Tk): def __init__(self): super().__init__() self.geometry('500x500') self.known_width = 500 self.known_height = 500 self.resizable(width=True, height=True) self.photo = Image.new('RGB', (256,256), (0,0,0)) self.display_photo = self.photo.copy() self.image = ImageTk.PhotoImage(self.display_photo) self.frame = tkinter.Frame(self) self.frame.pack(fill=tkinter.BOTH, expand=tkinter.YES) self.panel = tkinter.Label(self.frame) self.panel.pack(fill=tkinter.BOTH, expand=tkinter.YES) self.panel.bind('', self._resize_image) self.panel.configure(image=self.image) self.update() self._resize_image2() self.update() def _resize_image(self, event): self.known_width = event.width self.known_height = event.height self._resize_image2() def _resize_image2(self): size_tuple = (self.known_width, self.known_height) self.display_photo = self.photo.copy() self.display_photo.thumbnail(size_tuple) if self.display_photo is None: self.display_photo = self.photo self.image = ImageTk.PhotoImage(self.display_photo) self.panel.configure(image=self.image) def update_image(self, image, windowTile=None): if windowTile is not None: self.winfo_toplevel().title(str(windowTile)) self.photo = image self._resize_image2() self.update() userWantsPreview = False rootWindow = None if 'REDDITGETTER_PREVIEW' in os.environ and os.environ['REDDITGETTER_PREVIEW'] != '': userWantsPreview = True