rev |
line source |
paulo@60
|
1 import datetime
|
paulo@60
|
2 import cgi
|
paulo@60
|
3 import urlparse
|
paulo@60
|
4 import csv
|
paulo@60
|
5 import traceback
|
paulo@60
|
6
|
paulo@60
|
7 import html
|
paulo@60
|
8
|
paulo@78
|
9 import pinlib
|
paulo@78
|
10
|
paulo@60
|
11
|
paulo@60
|
12 DEBUG = True
|
paulo@60
|
13 STRTIME_FMT = "%Y-%m-%d %H:%M:%S"
|
paulo@60
|
14
|
paulo@60
|
15
|
paulo@60
|
16 class LLDialect(csv.Dialect):
|
paulo@60
|
17 delimiter = '\t'
|
paulo@60
|
18 quoting = csv.QUOTE_NONE
|
paulo@60
|
19 lineterminator = '\n'
|
paulo@60
|
20
|
paulo@60
|
21
|
paulo@60
|
22 LLDIALECT = LLDialect()
|
paulo@60
|
23 LLDB_FN = "lldb.tsv"
|
paulo@60
|
24 LLDB_UNREAD_FN = "lldb_unread.tsv"
|
paulo@60
|
25
|
paulo@60
|
26
|
paulo@60
|
27 class LLError(Exception):
|
paulo@60
|
28 pass
|
paulo@60
|
29
|
paulo@60
|
30 class PinFailError(LLError):
|
paulo@60
|
31 def __str__(self):
|
paulo@60
|
32 return "PIN FAIL!"
|
paulo@60
|
33
|
paulo@60
|
34 class MissingFieldsError(LLError):
|
paulo@60
|
35 def __str__(self):
|
paulo@60
|
36 return "MISSING FIELD(s)!"
|
paulo@60
|
37
|
paulo@60
|
38
|
paulo@60
|
39 def lldb_unread_load():
|
paulo@60
|
40 return csv.reader(open(LLDB_UNREAD_FN), LLDIALECT)
|
paulo@60
|
41
|
paulo@60
|
42
|
paulo@60
|
43 def lldb_add(inp):
|
paulo@60
|
44 try:
|
paulo@60
|
45 title = inp["title"][0]
|
paulo@60
|
46 url = inp["url"][0]
|
paulo@60
|
47 except (KeyError, IndexError):
|
paulo@60
|
48 raise MissingFieldsError()
|
paulo@60
|
49
|
paulo@60
|
50 dt_str = datetime.datetime.now().strftime(STRTIME_FMT)
|
paulo@60
|
51 with open(LLDB_FN, 'a') as lldb_f:
|
paulo@60
|
52 csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str])
|
paulo@60
|
53 with open(LLDB_UNREAD_FN, 'a') as lldb_f:
|
paulo@60
|
54 csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str])
|
paulo@60
|
55
|
paulo@60
|
56
|
paulo@60
|
57 def lldb_unread_delete(inp):
|
paulo@60
|
58 try:
|
paulo@60
|
59 delete = inp["delete"]
|
paulo@60
|
60 except KeyError:
|
paulo@60
|
61 raise MissingFieldsError()
|
paulo@60
|
62
|
paulo@60
|
63 lldb_unread = [i for i in lldb_unread_load()]
|
paulo@60
|
64 lldb_unread_f = open(LLDB_UNREAD_FN, 'w')
|
paulo@60
|
65
|
paulo@60
|
66
|
paulo@60
|
67 try:
|
paulo@60
|
68 for i in delete:
|
paulo@60
|
69 for j in lldb_unread:
|
paulo@60
|
70 dt_str = j[2]
|
paulo@60
|
71 if i == dt_str:
|
paulo@60
|
72 lldb_unread.remove(j)
|
paulo@60
|
73 finally:
|
paulo@60
|
74 csv.writer(lldb_unread_f, LLDIALECT).writerows(lldb_unread)
|
paulo@60
|
75 lldb_unread_f.close()
|
paulo@60
|
76
|
paulo@60
|
77
|
paulo@60
|
78
|
paulo@60
|
79 def parse_wsgi_input(environ):
|
paulo@60
|
80 return urlparse.parse_qs(environ["wsgi.input"].read())
|
paulo@60
|
81
|
paulo@60
|
82
|
paulo@60
|
83
|
paulo@60
|
84 def main(environ):
|
paulo@60
|
85 is_post = (environ["REQUEST_METHOD"] == "POST")
|
paulo@78
|
86 cookies = pinlib.parse_cookies(environ)
|
paulo@60
|
87 inp = parse_wsgi_input(environ)
|
paulo@60
|
88
|
paulo@60
|
89 if is_post:
|
paulo@78
|
90 try:
|
paulo@82
|
91 pinlib.PinMan("llpin").check(cookies)
|
paulo@78
|
92 except pinlib.PinFailError:
|
paulo@78
|
93 raise PinFailError
|
paulo@60
|
94 if inp["submit"][0] == "Add":
|
paulo@60
|
95 lldb_add(inp)
|
paulo@60
|
96 elif inp["submit"][0] == "Delete":
|
paulo@60
|
97 lldb_unread_delete(inp)
|
paulo@60
|
98
|
paulo@60
|
99 title = "later links..."
|
paulo@60
|
100 root = html.HTML("html")
|
paulo@60
|
101
|
paulo@96
|
102 header = root.head
|
paulo@60
|
103 header.link(rel="stylesheet", type="text/css", href="index.css")
|
paulo@60
|
104 header.title(title)
|
paulo@60
|
105
|
paulo@60
|
106 body = root.body
|
paulo@60
|
107 body.h1(title)
|
paulo@60
|
108
|
paulo@60
|
109
|
paulo@60
|
110 if (DEBUG):
|
paulo@60
|
111 debug = body.pre
|
paulo@60
|
112 for i in environ.items():
|
paulo@60
|
113 debug += cgi.escape("%s = %s \n" % i)
|
paulo@60
|
114
|
paulo@78
|
115 debug += cgi.escape("wsgi.input.read = %s \n" % inp)
|
paulo@78
|
116 debug += cgi.escape("cookies = %s \n" % cookies)
|
paulo@60
|
117
|
paulo@60
|
118 form = body.form(action="index.fcgi", method="post")
|
paulo@60
|
119
|
paulo@60
|
120 table = form.table
|
paulo@60
|
121 hrow = table.tr
|
paulo@60
|
122 hrow.th("Link")
|
paulo@60
|
123 hrow.th("Created")
|
paulo@60
|
124 hrow.th.input(type="submit", name="submit", value="Delete")
|
paulo@60
|
125
|
paulo@60
|
126 for i in lldb_unread_load():
|
paulo@60
|
127 (title, url, dt_str) = (j.decode("utf-8") for j in i)
|
paulo@60
|
128 row = table.tr
|
paulo@60
|
129 row.td.a(title, href=url)
|
paulo@60
|
130 row.td(dt_str)
|
paulo@60
|
131 row.td.input(type="checkbox", name="delete", value=dt_str)
|
paulo@60
|
132
|
paulo@60
|
133 p1 = form.p
|
paulo@60
|
134 p1.label("Title").input(type="text", name="title", size="64")
|
paulo@60
|
135 p1.br
|
paulo@60
|
136 p1.label("URL").input(type="text", name="url", size="64")
|
paulo@60
|
137 p1.br
|
paulo@60
|
138 p1.input(type="submit", name="submit", value="Add")
|
paulo@60
|
139
|
paulo@60
|
140 return unicode(root).encode("utf-8")
|
paulo@60
|
141
|
paulo@60
|
142
|
paulo@60
|
143 def app(environ, start_response):
|
paulo@60
|
144 response_code = "500 Internal Server Error"
|
paulo@60
|
145 response_type = "text/plain; charset=UTF-8"
|
paulo@60
|
146
|
paulo@60
|
147 try:
|
paulo@60
|
148 response_body = main(environ)
|
paulo@78
|
149 response_code = "200 OK"
|
paulo@60
|
150 response_type = "text/html; charset=UTF-8"
|
paulo@60
|
151 except LLError as e:
|
paulo@60
|
152 response_body = str(e)
|
paulo@60
|
153 except:
|
paulo@60
|
154 response_body = traceback.format_exc()
|
paulo@60
|
155
|
paulo@60
|
156 response_headers = [
|
paulo@60
|
157 ("Content-Type", response_type),
|
paulo@60
|
158 ("Content-Length", str(len(response_body))),
|
paulo@60
|
159 ]
|
paulo@60
|
160 start_response(response_code, response_headers)
|
paulo@60
|
161
|
paulo@60
|
162 return [response_body]
|