Merge branch 'master' of git.dolda2000.com:/srv/git/r/automanga
[automanga.git] / getmanga
CommitLineData
64eb9fa5
FT
1#!/usr/bin/python3
2
3import sys, os, getopt, time, random
4import manga.lib, manga.profile
5from PIL import Image
6
7verbose = 0
8wait = 10
9
10def msg(vl, msg, *args):
11 if verbose >= vl:
12 sys.stderr.write("getmanga: " + (msg % args) + "\n")
13
14def getprop(nm, default=None):
15 if "dl-" + nm in mprof.props:
16 return mprof.props["dl-" + nm]
17 if nm in props:
18 return props[nm]
19 return default
20
21def digits(num):
22 n, i = 10, 1
23 while True:
24 if num < n:
25 return i
26 n, i = n * 10, i + 1
27
28def autoname(page):
29 ret = ""
30 for t, i in page.stack:
31 if ret:
32 ret += "-"
33 ret += "%0*i" % (digits(len(t) + 1), i + 1)
34 return ret
35
36def expand(pattern, page):
37 ret = ""
38 si = 0
39 fp = 0
40 while True:
41 p = pattern.find('%', fp)
42 if p < 0:
43 if si < len(page.stack):
44 sys.stderr.write("getmanga: pattern %s did not match page %s\n" %
45 (pattern, "/".join(t.name for t, i in page.stack)))
46 sys.exit(1)
47 return ret + pattern[fp:]
48 ret += pattern[fp:p]
49 m = pattern[p:p + 1]
50 if m == "%":
51 ret += "%"
52 else:
53 if si >= len(page.stack):
54 sys.stderr.write("getmanga: pattern %s did not match page %s\n" %
55 (pattern, "/".join(t.name for t, i in page.stack)))
56 sys.exit(1)
57 t, ti = page.stack[si]
58 si += 1
59 if m == "i":
60 ret += "%0*i" % (digits(len(t) + 1), ti + 1)
61 elif m == "n":
62 ret += t.name
63 elif m == "d":
64 ret += t.id
65 else:
66 sys.stderr.write("getmanga: %s: unknown specified `%s'\n" % (m))
67 sys.exit(1)
68
69def download(mng, tdir, pattern):
70 exts = ["", ".jpg", ".jpeg", ".png", ".gif"]
71 fmts = {"PNG": "png", "JPEG": "jpeg", "GIF": "gif"}
72 for page in manga.lib.cursor(mng):
73 if pattern is None:
74 nm = autoname(page)
75 else:
76 nm = expand(pattern, page)
77 path = os.path.join(tdir, nm)
78 if any(os.path.exists(path + ext) for ext in exts):
79 msg(2, "%s exists, skipping", nm)
80 continue
81 msg(1, "getting %s...", nm)
82 with page.open() as fp:
83 with open(path, "wb") as out:
84 while True:
85 data = fp.read(65536)
86 if data == b"":
87 break
88 out.write(data)
89 try:
90 img = Image.open(path)
91 except OSError:
92 fmt = None
93 else:
94 fmt = img.format
95 if fmt not in fmts:
96 sys.stderr.write("getmanga: warning: could not determine file format of %s, leaving as is\n" % nm)
97 else:
98 os.rename(path, path + "." + fmts[fmt])
99 msg(3, "%s -> %s", nm, nm + "." + fmts[fmt])
100 cwait = abs(random.gauss(0, 1) * wait)
101 msg(2, "waiting %.1f s...", cwait)
102 time.sleep(cwait)
103
104def usage(out):
105 out.write("usage: getmanga [-hv] [-w WAIT] [-p PROFILE] DIRECTORY [LIBRARY ID]\n")
106
107def main():
108 global verbose, wait, mprof, props
109
110 opts, args = getopt.getopt(sys.argv[1:], "hvp:w:")
111 profnm = ""
112 for o, a in opts:
113 if o == "-h":
114 usage(sys.stdout)
115 sys.exit(0)
116 elif o == "-p":
117 profnm = a
118 elif o == "-v":
119 verbose += 1
120 elif o == "-w":
121 wait = int(a)
122 if len(args) < 1:
123 usage(sys.stderr)
124 sys.exit(1)
125 tdir = args[0]
126
127 if not os.path.isdir(tdir):
128 sys.stderr.write("getmanga: %s: not a directory\n" % (tdir))
129 sys.exit(1)
130
131 pfile = os.path.join(tdir, ".props")
132 props = {}
133 if os.path.exists(pfile):
134 with open(pfile, "r") as fp:
135 for words in splitlines(f):
136 if words[0] == "set" and len(words) > 2:
137 props[words[1]] = words[2]
138 elif words[0] == "lset" and len(words) > 1:
139 props[words[1]] = words[2:]
140
141 if profnm == "":
142 profile = manga.profile.profile.last()
143 else:
144 profile = manga.profile.profile.byname(profnm)
145
146 if len(args) == 2:
147 usage(sys.stderr)
148 sys.exit(1)
149 elif len(args) > 2:
150 libnm, mid = args[1:3]
151 elif isinstance(props.get("manga"), list):
152 libnm, mid = props["manga"]
153 else:
154 sys.stderr.write("getmanga: %s: id is neither saved nor given\n" % (tdir))
155 sys.exit(1)
156 try:
157 lib = manga.lib.findlib(libnm)
158 except ImportError:
159 sys.stderr.write("getmanga: no such library: %s\n" % (libnm))
160 sys.exit(1)
161 try:
162 mng = lib.byid(mid)
163 except KeyError:
164 sys.stderr.write("getmanga: no such manga: %s\n" % (mid))
165 sys.exit(1)
166 mprof = profile.getmanga(libnm, mng.id)
167
168 download(mprof.open(), tdir, getprop("pattern"))
169
170if __name__ == "__main__":
171 try:
172 main()
173 except KeyboardInterrupt:
174 pass