txkcd - scripts - random scripts
HTML git clone https://git.parazyd.org/scripts
DIR Log
DIR Files
DIR Refs
---
txkcd (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()