scripts

random scripts
git clone https://git.parazyd.org/scripts
Log | Files | Refs

xkcd (3822B)


      1 #!/usr/bin/env python
      2 #
      3 # grab a random xkcd comic, append title and alttext, and save to a dir
      4 
      5 from os import environ
      6 from re import search
      7 from random import randrange
      8 
      9 from PIL import Image, ImageDraw, ImageFont
     10 from requests import get
     11 
     12 DOWNLOAD_DIR = environ['HOME']+'/xkcd/'
     13 TITLE_FONTSIZE = 28
     14 ALT_FONTSIZE = 18
     15 LINE_OFFSET = 10
     16 
     17 def add_text(image, title, alt, tfont=DOWNLOAD_DIR+'xkcd.ttf',
     18              afont=DOWNLOAD_DIR+'xkcd.ttf'):
     19     try:
     20         img = Image.open(image)
     21     except OSError:
     22         return
     23 
     24     tfont = ImageFont.truetype(tfont, TITLE_FONTSIZE)
     25     afont = ImageFont.truetype(afont, ALT_FONTSIZE)
     26 
     27     line_padding = 5
     28     draw = ImageDraw.Draw(img)
     29     lines = text_wrap(tfont, title, img.size[0])
     30     lheight = max([tfont.getsize(" ".join(i))[1] for i in lines])
     31     lheight_total = (lheight+line_padding)*(len(lines))+line_padding*4
     32     title_crop = (0, -1*lheight_total, img.size[0], img.size[1])
     33     img = img.crop(title_crop)
     34     w, h = img.size
     35     old_h = h
     36     draw = ImageDraw.Draw(img)
     37     lheight_total = line_padding
     38     for i in lines:
     39         draw.text((w/2-tfont.getsize(" ".join(i))[0]/2, lheight_total),
     40                   " ".join(i), font=tfont, fill=0xffffff)
     41         lheight_total += lheight + line_padding
     42     lheight_total = line_padding
     43     lines = text_wrap(afont, alt, w)
     44     lheight = max([afont.getsize(" ".join(i))[1] for i in lines])
     45     lheight_total = lheight*len(lines)
     46     alt_crop = (0, 0, img.size[0],
     47                 img.size[1]+lheight_total+(len(lines)+3)*line_padding)
     48     img = img.crop(alt_crop)
     49     draw = ImageDraw.Draw(img)
     50     lheight_total = old_h + line_padding
     51     for i in lines:
     52         if not i:
     53             continue
     54         draw.text((w/2-afont.getsize(" ".join(i))[0]/2, lheight_total),
     55                   " ".join(i), font=afont, fill=0xffffff)
     56         lheight_total += lheight + line_padding
     57 
     58     img.save(image)
     59     print(image)
     60     exit(0)
     61 
     62 def text_wrap(font, text, image_width, i=0):
     63     lines = [[]]
     64     text = text.split(" ")
     65     while text:
     66         while text \
     67             and font.getsize(" ".join(lines[i]))[0] < image_width:
     68             if font.getsize(text[0]+" "+" ".join(lines[i]))[0] > image_width * 0.95:
     69                 if len(lines[i]) == 0:
     70                     text[0] = text[0][:len(text[0])//2+1] \
     71                         + " " + text[0][:len(text[0])//2+1:]
     72                     text = text[0].split(" ") + text[1:]
     73                 break
     74             lines[i].append(text[0])
     75             text.pop(0)
     76         i += 1
     77         lines.append([])
     78     sub = []
     79     for e, i in enumerate(lines):
     80         if font.getsize(" ".join(lines[e]))[0] > image_width:
     81             temp_str = ""
     82             for c in "".join(i):
     83                 if font.getsize(temp_str+c)[0] > image_width:
     84                     lines[i] = lines[i][:len(lines[i])//2] \
     85                         + lines[i][len(lines[i])//2:]
     86                     break
     87                 temp_str += c
     88             sub.append(temp_str)
     89             del lines[e]
     90     lines = [i for i in lines if len(i) != 0]
     91     for c in [i for i in sub if len(i) != 0]:
     92         lines.append(c)
     93     return lines
     94 
     95 def main():
     96     info = get("https://xkcd.com/info.0.json").json()
     97     if not info:
     98         exit(1)
     99     info = get("https://xkcd.com/"+str(randrange(1, info['num']) + 1)+"/info.0.json").json()
    100 
    101     title = info['safe_title']
    102     alt = info['alt']
    103     num = str(info['num'])
    104 
    105     image = num+search("\.([a-z])+$", info['img']).group()
    106 
    107     with open(DOWNLOAD_DIR+image, 'wb') as image_file:
    108         req = get(info['img'], stream=True)
    109         for block in req.iter_content(1024):
    110             if block:
    111                 image_file.write(block)
    112                 image_file.flush()
    113         if not search("\.gif", info['img']):
    114             add_text(DOWNLOAD_DIR+image, title, alt)
    115 
    116 main()