3 import sys, os, getopt, time, random
4 import manga.lib, manga.profile
11 def msg(vl, msg, *args):
13 sys.stderr.write("getmanga: " + (msg % args) + "\n")
15 def getprop(nm, default=None):
16 if mprof and "dl-" + nm in mprof.props:
17 return mprof.props["dl-" + nm]
32 for t, i in page.stack:
34 inames.append((t, ret))
37 ret += "%0*i" % (digits(len(t) + 1), i + 1)
40 def expand(pattern, page):
45 stack = list(zip([t for t, i in page.stack], [t for t, i in page.stack[1:]] + [page], [i for t, i in page.stack]))
47 p = pattern.find('%', fp)
50 sys.stderr.write("getmanga: pattern %s did not match page %s\n" %
51 (pattern, "/".join(c.name for t, c, i in stack)))
53 return ret + pattern[fp:], inames
55 m = pattern[p + 1:p + 2]
61 sys.stderr.write("getmanga: pattern %s did not match page %s\n" %
62 (pattern, "/".join(c.name for t, c, i in stack)))
67 ret += "%0*i" % (digits(len(t) + 1), ti + 1)
73 sys.stderr.write("getmanga: %s: unknown specifier `%s'\n" % (pattern, m))
76 inames.append((ct, ret))
79 def checknames(tdir, names):
81 nmpath = os.path.join(tdir, "names")
82 if checkednames is None:
84 if os.path.exists(nmpath):
85 with open(nmpath) as fp:
90 checkednames[line[:p]] = line[p + 1:]
91 for t, prefix in names:
92 if not prefix: continue
93 if ' ' not in prefix and prefix not in checkednames:
94 with manga.profile.txfile(nmpath, "w") as fp:
95 if '\n' not in t.name:
96 checkednames[prefix] = t.name
97 msg(1, "adding name %s for %s" % (t.name, prefix))
99 checkednames[prefix] = ""
100 sys.stderr.write("getmanga: warning: node names contains newlines: %r\n" % (t.name,))
101 for prefix, name in checkednames.items():
102 if not name: continue
103 fp.write("%s %s\n" % (prefix, name))
105 def download(mng, tdir, pattern):
106 exts = ["", ".jpg", ".jpeg", ".png", ".gif"]
107 fmts = {"PNG": "png", "JPEG": "jpeg", "GIF": "gif"}
108 for page in manga.lib.cursor(mng):
110 nm, inames = autoname(page)
112 nm, inames = expand(pattern, page)
114 checknames(tdir, inames)
115 path = os.path.join(tdir, nm)
116 if any(os.path.exists(path + ext) for ext in exts):
117 msg(2, "%s exists, skipping", nm)
119 msg(1, "getting %s...", nm)
125 except OSError as error:
127 sys.stderr.write("getmanga: warning: error when getting %s: %s\n" % (nm, error))
131 sys.stderr.write("getmanga: error when getting %s: %s\n" % (nm, error))
134 with open(path, "wb") as out:
138 data = fp.read(65536)
147 img = Image.open(path)
153 sys.stderr.write("getmanga: warning: could not determine file format of %s, leaving as is\n" % nm)
155 os.rename(path, path + "." + fmts[fmt])
156 msg(3, "%s -> %s", nm, nm + "." + fmts[fmt])
157 cwait = abs(random.gauss(0, 1) * wait)
158 msg(2, "waiting %.1f s...", cwait)
162 out.write("usage: getmanga [-hvn] [-w WAIT] [-p PROFILE] [-P PATTERN] DIRECTORY [LIBRARY ID]\n")
163 out.write("\tpattern templates:\n")
164 out.write("\t %i\tSequence number\n")
165 out.write("\t %n\tName\n")
166 out.write("\t %d\tID\n")
169 global verbose, wait, mprof, props, getnames
171 opts, args = getopt.getopt(sys.argv[1:], "hvnp:w:P:")
193 if not os.path.isdir(tdir):
194 sys.stderr.write("getmanga: %s: not a directory\n" % (tdir))
197 pfile = os.path.join(tdir, ".props")
199 if os.path.exists(pfile):
200 with open(pfile, "r") as fp:
201 for words in manga.profile.splitlines(fp):
202 if words[0] == "set" and len(words) > 2:
203 props[words[1]] = words[2]
204 elif words[0] == "lset" and len(words) > 1:
205 props[words[1]] = words[2:]
208 profile = manga.profile.profile.last()
212 profile = manga.profile.profile.byname(profnm)
214 if props.get("getnames", "") == "yes":
221 libnm, mid = args[1:3]
222 elif isinstance(props.get("manga"), list):
223 libnm, mid = props["manga"]
225 sys.stderr.write("getmanga: %s: id is neither saved nor given\n" % (tdir))
228 lib = manga.lib.findlib(libnm)
230 sys.stderr.write("getmanga: no such library: %s\n" % (libnm))
235 sys.stderr.write("getmanga: no such manga: %s\n" % (mid))
237 if profile is not None:
238 mprof = profile.getmanga(libnm, mng.id)
242 download(mng, tdir, pattern or getprop("pattern"))
244 if __name__ == "__main__":
247 except KeyboardInterrupt: