lawn-mower.py - gopher-lawn - The gopher lawn gopher directory project.
(HTM) git clone git://bitreich.org/gopher-lawn/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/gopher-lawn/
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
---
lawn-mower.py (6722B)
---
1 #!/usr/bin/env python
2 # coding=utf-8
3 #
4 # © 2020 Christoph Lohmann <20h@r-36.net>
5 #
6 # This file is published under the terms of the GPLv3.
7 #
8
9 import os
10 import sys
11 import getopt
12
13 def usage(app):
14 app = os.path.basename(app)
15 print("usage: %s [-h] [-b basedir] [-c categorydir] " \
16 "[-s selectorbase]" \
17 % (app), file=sys.stderr)
18 sys.exit(1)
19
20 def main(args):
21 try:
22 opts, largs = getopt.getopt(args[1:], "hc:s:")
23 except getopt.GetoptError as err:
24 print(str(err))
25 usage(args[0])
26
27 basedir = "./"
28 categorysubdir = "/c"
29 selectorbase = "/lawn"
30 for o, a in opts:
31 if o == "-h":
32 usage(args[0])
33 elif o == "-b":
34 basedir = a
35 elif o == "-c":
36 categorysubdir = a
37 elif o == "-s":
38 selectorbase = a
39 else:
40 assert False, "unhandled option"
41
42 categorydir = "%s%s" % (basedir, categorysubdir)
43 categoryselector = "%s%s" % (selectorbase, categorysubdir)
44
45 filelist = largs
46 if len(largs) == 0:
47 filelist = ["/dev/stdin"]
48
49 dbobjs = []
50 dbobj = {}
51 for f in filelist:
52 dbobj = {}
53 dbkey = None
54 dbval = None
55 with open(f, "r") as fd:
56 while True:
57 line = fd.readline()
58 # EOF
59 if line == "":
60 #print("EOF")
61 if dbobj != {}:
62 dbobjs.append(dbobj)
63 dbobj = {}
64 break
65
66 if line[0] == "#":
67 continue
68
69 line = line.rstrip()
70 #print("line = '%s'" % (line))
71 if line == "":
72 #print("line empty")
73 if dbobj != {}:
74 dbobjs.append(dbobj)
75 dbobj = {}
76 continue
77
78 # Multi line value.
79 if line[0] in ["\f", "\t", "\v", " "]:
80 #print("multi-line")
81 if dbkey != None:
82 dbobj[dbkey] += " %s" % (line.lstrip())
83 continue
84
85 try:
86 (dbkey, dbval) = line.split(":", 1)
87 except ValueError:
88 sys.write(sys.stderr, "'%s' is invalid line at %s.\n" \
89 % (line, f))
90 continue
91
92 #print("dbkey = %s; dbval = %s" % (dbkey, dbval))
93
94 dbkey = dbkey.strip().lower()
95 dbval = dbval.lstrip()
96 dbobj[dbkey] = dbval
97
98 rootcategory = None
99 categories = {}
100 wantedcategories = {}
101 wantedkeywords = {}
102 keywords = {}
103 links = []
104 noncategories = []
105 nonkeywords = []
106 for obj in dbobjs:
107 if "category" in obj:
108 ocats = obj["category"].split(", ")
109 if len(ocats) == 0 or ocats[0] == '':
110 noncategories.append(obj)
111 obj["category"] = ocats
112 for ocat in ocats:
113 if ocat in wantedcategories:
114 wantedcategories[ocat].append(obj)
115 else:
116 wantedcategories[ocat] = [obj]
117 if "keywords" in obj:
118 okeyws = obj["keywords"].split(", ")
119 if len(okeyws) == 0 or okeyws[0] == '':
120 nonkeywords.append(obj)
121 for okeyw in okeyws:
122 if okeyw in wantedkeywords:
123 wantedkeywords[okeyw].append(obj)
124 else:
125 wantedkeywords[okeyw] = [obj]
126 if obj["type"] == "category":
127 if obj["parent"] == "none":
128 rootcategory = obj
129 if obj["name"] in categories:
130 print("Duplication of category '%s'." \
131 % (obj["name"]))
132 sys.exit(1)
133 obj["links"] = []
134 obj["children"] = []
135 categories[obj["name"]] = obj
136 else:
137 links.append(obj)
138
139 #print(categories.keys())
140 keywords = wantedkeywords
141 #print(wantedkeywords.keys())
142 #print(keywords.keys())
143 #print(wantedcategories.keys())
144 #print(noncategories)
145 #print(nonkeywords)
146
147 for link in links:
148 if "category" in link:
149 for cate in link["category"]:
150 categories[cate]["links"].append(link)
151
152 for key in categories.keys():
153 parent = categories[key]["parent"]
154 if parent in categories.keys():
155 categories[parent]["children"].append(key)
156 else:
157 if parent != "none":
158 print("Undefined parent '%s' used in category '%s'." \
159 % (parent, key))
160
161 for obj in noncategories:
162 print("'%s' has no categories defined." \
163 % (obj["linkname"]))
164 for obj in nonkeywords:
165 print("'%s' has no keywords defined." \
166 % (obj["linkname"]))
167
168 def linktype2gopher(link):
169 linktype = link["type"]
170 if linktype == "link":
171 if link["selector"].startswith("URL:"):
172 return "h"
173 return "1"
174 elif linktype == "text":
175 return "0"
176 elif linktype == "cso":
177 return "2"
178 elif linktype == "error":
179 return "3"
180 elif linktype == "uuencoded":
181 return "6"
182 elif linktype == "search":
183 return "7"
184 elif linktype == "telnet":
185 return "8"
186 else:
187 return "9"
188
189 def printdescription(desc):
190 maxlinelen = 70
191 if len(desc) <= maxlinelen:
192 return "%s\n" % (desc)
193
194 rtext = ""
195 adesc = desc
196 while len(adesc) > maxlinelen:
197 pline = ""
198 i = 70
199 while i > maxlinelen-20:
200 if adesc[i] in [" ", "\t", "\v", "\f", "-"]:
201 rtext += "%s\n" % (adesc[:i])
202 adesc = adesc[i+1:]
203 break
204 i -= 1
205 if i <= maxlinelen-20:
206 rtext += "%s\n" % (adesc[:maxlinelen])
207 adesc = adesc[maxlinelen:]
208 rtext += "%s\n" % (adesc)
209
210 return rtext
211
212 def printlink(link):
213 try:
214 rtext = "[%s|%s|%s|%s|%s]\n" \
215 % (linktype2gopher(link),\
216 link["linkname"],\
217 link["selector"],\
218 link["host"],\
219 link["port"])
220 except KeyError:
221 print("Error printing link in: %s" % (link))
222 return ""
223
224 if "description" in link:
225 rtext += printdescription(link["description"])
226 rtext += "\n"
227
228 return rtext
229
230 def printcategory(category, basedir):
231 if "description" in category:
232 name = "%s - %s" \
233 % (category["linkname"], \
234 category["description"])
235 else:
236 name = category["linkname"]
237 return "[1|%s|%s|%s|%s]\n" \
238 % (name,\
239 "%s/%s.gph" % (basedir, category["name"]),\
240 "server",\
241 "port")
242
243 def mkcategory(category, cdir, csdir, tmplfile="category.gph.tmpl"):
244 outfilename = tmplfile.replace(".tmpl", "")
245 if "category" in tmplfile:
246 outfilename = outfilename.replace("category",\
247 category["name"])
248
249 tmplfd = open(tmplfile, "r")
250 try:
251 outfd = open("%s/%s" % (cdir, outfilename), "x")
252 except FileExistsError:
253 outfd = open("%s/%s" % (cdir, outfilename), "w")
254
255 line = "a"
256 while len(line) > 0:
257 line = tmplfd.readline()
258 if "C_A_T_E_G_O_R_Y" in line:
259 if len(category["links"]) > 0:
260 line = line.replace("C_A_T_E_G_O_R_Y", \
261 category["title"])
262 outfd.write(line)
263 if "description" in category:
264 outfd.write(printdescription(\
265 category["description"]))
266 outfd.write("\n")
267 for link in category["links"]:
268 outfd.write(printlink(link))
269 elif "C_A_T_E_G_O_R_I_E_S" in line:
270 if len(category["children"]) > 0:
271 outfd.write(line)
272 for cate in category["children"]:
273 outfd.write(\
274 printcategory(\
275 categories[cate],\
276 csdir))
277 else:
278 outfd.write(line)
279
280 tmplfd.close()
281 outfd.close()
282
283 mkcategory(rootcategory, basedir, categoryselector, "index.gph.tmpl")
284 for c in categories.keys():
285 mkcategory(categories[c], categorydir, categoryselector,\
286 "category.gph.tmpl")
287 return 0
288
289 if __name__ == "__main__":
290 sys.exit(main(sys.argv))
291