local: Treat dots/periods as digits in destructuring directories.
[automanga.git] / automanga
1 #!/usr/bin/python3
2
3 import sys, getopt, pathlib
4 import manga.lib, manga.reader, manga.profile, manga.local
5 from gi.repository import Gtk, Gdk, GObject
6
7 def usage(out):
8     out.write("usage: automanga [-h] [-p PROFILE] {DIRECTORY|-l LIBRARY ID|-a ALIAS}\n")
9     out.write("       automanga -a ALIAS=LIBRARY:ID\n")
10     out.write("       automanga -t {DIRECTORY|-l LIBRARY ID|-a ALIAS} [-]TAG...\n")
11     out.write("       automanga -{s|S} LIBRARY NAME\n")
12     out.write("       automanga -L TAG [-o ORDER]\n")
13
14 libname = None
15 search = None
16 profile = ""
17 alias = None
18 settags = False
19 listtag = None
20 listorder = None
21 opts, args = getopt.getopt(sys.argv[1:], "hl:sSp:a:tL:o:")
22 for o, a in opts:
23     if o == "-h":
24         usage(sys.stdout)
25         sys.exit(0)
26     elif o == "-l":
27         libname = a
28     elif o == "-a":
29         alias = a
30     elif o == "-s":
31         search = "name"
32     elif o == "-S":
33         search = "match"
34     elif o == "-p":
35         if a == "":
36             profile = None
37         else:
38             profile = a
39     elif o == "-t":
40         settags = True
41     elif o == "-L":
42         listtag = a
43     elif o == "-o":
44         listorder = a
45 if profile == "":
46     try:
47         profile = manga.profile.profile.last()
48     except KeyError:
49         profile = manga.profile.profile.byname("default")
50 elif profile is not None:
51     profile = manga.profile.profile.byname(profile)
52
53 def main():
54     global libname
55
56     if search:
57         if len(args) < 2:
58             usage(sys.stderr)
59             sys.exit(1)
60         try:
61             lib = manga.lib.findlib(args[0])
62         except ImportError:
63             sys.stderr.write("automanga: no such library: %s\n" % args[0])
64             sys.exit(1)
65         try:
66             if search == "name":
67                 results = lib.byname(args[1])
68             elif search == "match":
69                 results = lib.search(args[1])
70                 if hasattr(results, "__length_hint__"):
71                     sys.stderr.write("%i results:\n" % results.__length_hint__())
72         except NotImplementedError:
73             sys.stderr.write("automanga: %s does not support searching\n" % args[0])
74             sys.exit(1)
75         for mng in results:
76             sys.stdout.write("\"%s\": %s\n" % (mng.name, mng.id))
77         return
78
79     if listtag is not None:
80         if profile is not None:
81             results = []
82             for mprof in profile.bytag(listtag):
83                 try:
84                     mng = mprof.open()
85                 except KeyError:
86                     sys.stderr.write("%s %s: no longer found\n" % (mprof.libnm, mprof.id))
87                     continue
88                 except Exception as exc:
89                     sys.stderr.write("%s %s: unexpected error: %s\n" % (mprof.libnm, mprof.id, str(exc)))
90                     continue
91                 line = "%s %s: \"%s\"" % (mprof.libnm, mprof.id, mng.name)
92                 if listorder is None:
93                     sys.stdout.write("%s\n" % (line,))
94                 else:
95                     if listorder == "mtime":
96                         key = -mprof.mtime()
97                     else:
98                         sys.stderr.write("automanga: undefined order: %s\n" % (listorder,))
99                         sys.exit(1)
100                     results.append((line, key))
101             if len(results) > 0:
102                 results.sort(key=lambda o: o[1])
103                 for line, key in results:
104                     sys.stdout.write("%s\n" % (line,))
105         return
106
107     if alias and (alias.find('=') > 0):
108         tgt, nm = alias.split('=', 1)
109         if not ':' in nm:
110             usage(sys.stderr)
111             sys.exit(1)
112         libname, mid = nm.split(':', 1)
113         try:
114             lib = manga.lib.findlib(libname)
115         except ImportError:
116             sys.stderr.write("automanga: no such library: %s\n" % libname)
117             sys.exit(1)
118         try:
119             mng = lib.byid(mid)
120         except KeyError as e:
121             sys.stderr.write("automanga: no such manga: %s\n" % str(e))
122             sys.exit(1)
123         profile.setalias(tgt, libname, mng.id)
124         return
125
126     if alias:
127         try:
128             libname, mid = profile.getalias(alias)
129         except KeyError:
130             sys.stderr.write("automanga: no such alias: %s\n" % alias)
131             sys.exit(1)
132         try:
133             lib = manga.lib.findlib(libname)
134         except ImportError:
135             sys.stderr.write("automanga: no such library: %s\n" % libname)
136             sys.exit(1)
137         try:
138             mng = lib.byid(mid)
139         except KeyError:
140             sys.stderr.write("automanga: manga no longer found: %s\n" % mid)
141             sys.exit(1)
142     elif libname is not None:
143         if len(args) < 1:
144             usage(sys.stderr)
145             sys.exit(1)
146         try:
147             lib = manga.lib.findlib(libname)
148         except ImportError:
149             sys.stderr.write("automanga: no such library: %s\n" % libname)
150             sys.exit(1)
151         try:
152             mng = lib.byid(args.pop(0))
153         except KeyError as e:
154             sys.stderr.write("automanga: no such manga: %s\n" % str(e))
155             sys.exit(1)
156     else:
157         libname = "local"
158         try:
159             if len(args) < 1:
160                 usage(sys.stderr)
161                 sys.exit(1)
162             mdir = args.pop(0)
163             mng = manga.local.manga(pathlib.Path(mdir))
164         except TypeError:
165             sys.stderr.write("automanga: not a valid manga directory: %s\n" % mdir)
166             sys.exit(1)
167
168     mprof = None if profile is None else profile.getmanga(libname, mng.id, True)
169     if profile is not None:
170         profile.setlast()
171
172     if settags:
173         if mprof is not None:
174             ntags = [tag for tag in args if tag[:1] != "-"]
175             rtags = [tag[1:] for tag in args if tag[:1] == "-"]
176             if ntags: mprof.tags.add(*ntags)
177             if rtags: mprof.tags.remove(*rtags)
178         return
179
180     reader = manga.reader.reader(mng, mprof)
181     reader.show()
182     Gtk.main()
183
184 try:
185     main()
186 except KeyboardInterrupt:
187     pass