changeset 117:476cb019ad9f

add laterlinks3
author paulo
date Tue, 08 Sep 2020 23:52:57 -0700
parents cb963b1875f7
children 65db090a697e
files laterlinks3/laterlinks_flask_app.py laterlinks3/lldb.tsv laterlinks3/lldb_unread.tsv laterlinks3/requirements.pip laterlinks3/static/index.css
diffstat 5 files changed, 158 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/laterlinks3/laterlinks_flask_app.py	Tue Sep 08 23:52:57 2020 -0700
     1.3 @@ -0,0 +1,127 @@
     1.4 +import csv
     1.5 +import datetime
     1.6 +import os
     1.7 +
     1.8 +import flask
     1.9 +
    1.10 +from html3.html3 import HTML
    1.11 +
    1.12 +app = flask.Flask(__name__)
    1.13 +
    1.14 +PIN = os.environ.get('LLPIN')
    1.15 +STRTIME_FMT = "%Y-%m-%d %H:%M:%S"
    1.16 +
    1.17 +
    1.18 +class LLDialect(csv.Dialect):
    1.19 +  delimiter = '\t'
    1.20 +  quoting = csv.QUOTE_NONE
    1.21 +  lineterminator = '\n'
    1.22 +
    1.23 +
    1.24 +LLDIALECT = LLDialect()
    1.25 +LLDB_FN = "lldb.tsv"
    1.26 +LLDB_UNREAD_FN = "lldb_unread.tsv"
    1.27 +
    1.28 +
    1.29 +class LLError(Exception):
    1.30 +  pass
    1.31 +
    1.32 +class PinFailError(LLError):
    1.33 +  def __str__(self):
    1.34 +    return "PIN FAIL!"
    1.35 +
    1.36 +class PinSetupError(LLError):
    1.37 +  def __str__(self):
    1.38 +    return "PIN SETUP ERROR!"
    1.39 +
    1.40 +class MissingFieldsError(LLError):
    1.41 +  def __str__(self):
    1.42 +    return "MISSING FIELD(s)!"
    1.43 +
    1.44 +
    1.45 +def lldb_unread_load():
    1.46 +  return csv.reader(open(LLDB_UNREAD_FN), LLDIALECT)
    1.47 +
    1.48 +
    1.49 +def lldb_add(inp):
    1.50 +  title = inp.get("title")
    1.51 +  url = inp.get("url")
    1.52 +  if not (title and url):
    1.53 +    raise MissingFieldsError()
    1.54 +
    1.55 +  dt_str = datetime.datetime.now().strftime(STRTIME_FMT)
    1.56 +  with open(LLDB_FN, 'a') as lldb_f:
    1.57 +    csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str])
    1.58 +  with open(LLDB_UNREAD_FN, 'a') as lldb_f:
    1.59 +    csv.writer(lldb_f, LLDIALECT).writerow([title, url, dt_str])
    1.60 +
    1.61 +
    1.62 +def lldb_unread_delete(inp):
    1.63 +  delete = inp.getlist("delete")
    1.64 +  if not delete:
    1.65 +    raise MissingFieldsError()
    1.66 +
    1.67 +  lldb_unread = [i for i in lldb_unread_load()]
    1.68 +  lldb_unread_f = open(LLDB_UNREAD_FN, 'w')
    1.69 +
    1.70 +  try:
    1.71 +    for i in delete:
    1.72 +      for j in lldb_unread:
    1.73 +        dt_str = j[2]
    1.74 +        if i == dt_str:
    1.75 +          lldb_unread.remove(j)
    1.76 +  finally:
    1.77 +    csv.writer(lldb_unread_f, LLDIALECT).writerows(lldb_unread)
    1.78 +    lldb_unread_f.close()
    1.79 +  
    1.80 +    
    1.81 +
    1.82 +@app.route("/", methods=["GET", "POST"])
    1.83 +def index():
    1.84 +  is_post = (flask.request.method == "POST")
    1.85 +  inp = flask.request.form
    1.86 +  cookies = flask.request.cookies
    1.87 +
    1.88 +  if is_post:
    1.89 +    if not PIN:
    1.90 +      raise PinSetupError
    1.91 +    elif cookies.get("llpin") != PIN:
    1.92 +      raise PinFailError
    1.93 +
    1.94 +    if inp["submit"] == "Add":
    1.95 +      lldb_add(inp)
    1.96 +    elif inp["submit"] == "Delete":
    1.97 +      lldb_unread_delete(inp)
    1.98 +
    1.99 +  title = "later links..."
   1.100 +  root = HTML("html")
   1.101 +
   1.102 +  header = root.head
   1.103 +  header.link(rel="stylesheet", type="text/css", href=flask.url_for("static", filename="index.css"))
   1.104 +  header.title(title)
   1.105 +  
   1.106 +  body = root.body
   1.107 +  body.h1(title)
   1.108 +
   1.109 +  form = body.form(action="/", method="post")
   1.110 +
   1.111 +  table = form.table
   1.112 +  hrow = table.tr
   1.113 +  hrow.th("Link")
   1.114 +  hrow.th("Created")
   1.115 +  hrow.th.input(type="submit", name="submit", value="Delete")
   1.116 +
   1.117 +  for (title, url, dt_str) in lldb_unread_load():
   1.118 +    row = table.tr
   1.119 +    row.td.a(title, href=url)
   1.120 +    row.td(dt_str)
   1.121 +    row.td.input(type="checkbox", name="delete", value=dt_str)
   1.122 +
   1.123 +  p1 = form.p
   1.124 +  p1.label("Title").input(type="text", name="title", size="64")
   1.125 +  p1.br
   1.126 +  p1.label("URL").input(type="text", name="url", size="64")
   1.127 +  p1.br
   1.128 +  p1.input(type="submit", name="submit", value="Add")
   1.129 +
   1.130 +  return str(root).encode("utf-8")
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/laterlinks3/lldb.tsv	Tue Sep 08 23:52:57 2020 -0700
     2.3 @@ -0,0 +1,1 @@
     2.4 +title0	url0	2020-09-08 23:50:23
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/laterlinks3/lldb_unread.tsv	Tue Sep 08 23:52:57 2020 -0700
     3.3 @@ -0,0 +1,1 @@
     3.4 +title0	url0	2020-09-08 23:50:23
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/laterlinks3/requirements.pip	Tue Sep 08 23:52:57 2020 -0700
     4.3 @@ -0,0 +1,8 @@
     4.4 +click==7.1.2
     4.5 +Flask==1.1.2
     4.6 +gunicorn==20.0.4
     4.7 +html3==1.18
     4.8 +itsdangerous==1.1.0
     4.9 +Jinja2==2.11.2
    4.10 +MarkupSafe==1.1.1
    4.11 +Werkzeug==1.0.1
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/laterlinks3/static/index.css	Tue Sep 08 23:52:57 2020 -0700
     5.3 @@ -0,0 +1,21 @@
     5.4 +body
     5.5 +{
     5.6 +  background-color: #111;
     5.7 +  color: #ccc;
     5.8 +}
     5.9 +
    5.10 +a:link
    5.11 +{
    5.12 +  color: #831;
    5.13 +}
    5.14 +
    5.15 +a:visited
    5.16 +{
    5.17 +  color: gray;
    5.18 +}
    5.19 +
    5.20 +div {
    5.21 +  text-align: center;
    5.22 +  line-height: 2;
    5.23 +  font-size: 500%;
    5.24 +}