Browse Source

JSON responses, latest + today + past requests work, web interface is pink, header image added

master
manetta 3 years ago
parent
commit
c59d206bed
  1. 121
      feedtools.py
  2. 31
      start.py
  3. 38
      static/css/stylesheet.css
  4. 81
      static/img/multifeeder.svg
  5. 45
      templates/index.html

121
feedtools.py

@ -3,80 +3,99 @@ from simpledatabase import SimpleDatabase
import json import json
from datetime import date, timedelta from datetime import date, timedelta
def load(): def update():
""" Load all feeds """ """ Update all feeds """
feeds = open('feeds.txt').readlines() feeds = open('feeds.txt').readlines()
db = SimpleDatabase('feeds.json', 'feeds.log') db = SimpleDatabase('feeds.json', 'feeds.log')
tmp = {} tmp = {}
tmp['feeds'] = {}
tmp['all_posts_sorted'] = {}
for x, feed in enumerate(feeds): for x, feed in enumerate(feeds):
parsed = feedparser.parse(feed) parsed = feedparser.parse(feed)
x = str(x) x = str(x)
tmp[x] = {}
tmp[x]['title'] = parsed.feed.title print(parsed)
tmp[x]['link'] = parsed.feed.link
tmp[x]['description'] = parsed.feed.description tmp['feeds'][x] = {}
tmp[x]['entries'] = parsed.entries tmp['feeds'][x]['title'] = parsed.feed.title
tmp['feeds'][x]['link'] = parsed.feed.link
tmp['feeds'][x]['description'] = parsed.feed.description
for post in parsed.entries:
year = post['published_parsed'][0]
month = post['published_parsed'][1]
day = post['published_parsed'][2]
post_date = date(year, month, day)
if not str(post_date) in tmp['all_posts_sorted']:
tmp['all_posts_sorted'][str(post_date)] = []
post['feed_details'] = {}
post['feed_details']['title'] = parsed.feed.title
post['feed_details']['link'] = parsed.feed.link
post['feed_details']['description'] = parsed.feed.description
tmp['all_posts_sorted'][str(post_date)].append(post)
db.update(tmp) db.update(tmp)
return db return db
def load():
db = SimpleDatabase('feeds.json', 'feeds.log')
return db
def latest(num): def latest(num):
""" Placeholder request """ """ Collect the <num> latest published posts """
request = [ db = load()
{
"feedtitle" : "Varia EN", dates = [key for key in db['all_posts_sorted'].keys()]
"post": "hello world", dates.sort(reverse=True)
"date" : "Monday 15th of February 2021", request = []
"url" : "https://vvvvvvaria.org/en/rr-wireless-imagination-1.html"
} for date in dates:
] posts = db['all_posts_sorted'][date]
for post in posts:
if len(request) < int(num):
request.append(post)
else:
break
return request return request
def today(): def today():
""" Collect posts from today """ """ Collect posts from today """
db = load() db = load()
today = date.today()
request = []
today = str(date.today()).split('-') for date_str, posts in db['all_posts_sorted'].items():
today_year = "{:02d}".format(int(today[0])) year = int(date_str.split('-')[0])
today_month = "{:02d}".format(int(today[1])) month = int(date_str.split('-')[1])
today_day = "{:02d}".format(int(today[2])) day = int(date_str.split('-')[2])
print('TODAY =', today_year, today_month, today_day) d = date(year, month, day)
# Check if any posts are published today
if d == today:
for post in posts:
request.append(post)
request = []
for x, feed in db.items():
for post in feed['entries']:
if post['published_parsed']:
year = "{:02d}".format(post['published_parsed'][0])
month = "{:02d}".format(post['published_parsed'][1])
day = "{:02d}".format(post['published_parsed'][2] + 1)
print('POST DATE =', year, month, day)
# Check if this post is published today
if year == today_year:
if month == today_month:
if day == today_day:
request.append(post)
return request return request
def past(days): def past(days):
""" Collect posts from this week """ """ Collect posts from this week """
db = load() db = load()
point_in_the_past = date.today() - timedelta(int(days)) point_in_the_past = date.today() - timedelta(int(days))
print(f"{ days } days in the past =", point_in_the_past)
request = [] request = []
for x, feed in db.items():
for post in feed['entries']: for date_str, posts in db['all_posts_sorted'].items():
if post['published_parsed']: year = int(date_str.split('-')[0])
year = post['published_parsed'][0] month = int(date_str.split('-')[1])
month = post['published_parsed'][1] day = int(date_str.split('-')[2])
day = post['published_parsed'][2] d = date(year, month, day)
post_date = date(year, month, day) if d > point_in_the_past:
print("post date =",post_date) for post in posts:
request.append(post)
if post_date > point_in_the_past:
request.append(post)
return request return request

31
start.py

@ -1,5 +1,6 @@
import flask import flask
import feedtools import feedtools
import json
APP = flask.Flask(__name__, APP = flask.Flask(__name__,
static_url_path="", static_url_path="",
@ -11,26 +12,42 @@ def index():
db = feedtools.load() db = feedtools.load()
template = flask.render_template( template = flask.render_template(
"index.html", "index.html",
feeds=db, db=db,
) )
return template return template
# @APP.route("/API/latest/<num>") @APP.route("/API/latest/<num>")
# def latest(num): def latest(num):
# request = feedtools.latest(num) request = feedtools.latest(num)
# return request response = APP.response_class(
response=json.dumps(request),
status=200,
mimetype='application/json'
)
return response
@APP.route("/API/today/") @APP.route("/API/today/")
def today(): def today():
request = feedtools.today() request = feedtools.today()
return str(request) response = APP.response_class(
response=json.dumps(request),
status=200,
mimetype='application/json'
)
return response
@APP.route("/API/past/<days>") @APP.route("/API/past/<days>")
def past(days): def past(days):
request = feedtools.past(days) request = feedtools.past(days)
return str(request) response = APP.response_class(
response=json.dumps(request),
status=200,
mimetype='application/json'
)
return response
if __name__ == "__main__": if __name__ == "__main__":
feedtools.update()
APP.debug = True APP.debug = True
APP.run(port=5678) APP.run(port=5678)

38
static/css/stylesheet.css

@ -1,14 +1,21 @@
body{ body{
background-color: pink; background-color: pink;
color: red; /*color: red;*/
margin: 1em; margin: 1em;
font-size: 16px;
line-height: 1.6;
} }
h1,
h2{ h1#title{
margin: 1em; width: 100%;
text-align: center;
margin: 1em auto;
}
h1#title img{
width: 500px;
} }
h2{ h2{
color: fuchsia; margin: 0 0 1em;
} }
table{ table{
@ -16,22 +23,31 @@ table{
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
} }
table tr{
border-bottom: 20px solid white;
}
table td{ table td{
padding: 1em 2em; padding: 1em 2em;
vertical-align: top;
} }
table td:first-of-type{ table td:first-of-type{
width: 100px; width: 100px;
} }
table tr{
border-bottom: 20px solid white;
}
section#api{ section#api{
margin: 6em 0; margin: 6em 0em;
color: fuchsia; color: fuchsia;
} }
section#api div.accesspoint{ section#api div.accesspoint{
margin: 0; margin: 0;
padding: 1em; padding: 1em 2em;
border-bottom: 20px solid yellow; border-bottom: 20px solid black;
}
a,
a:active,
a:visited,
a:hover{
text-decoration-line: underline;
color: inherit;
} }

81
static/img/multifeeder.svg

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="200mm"
height="50mm"
viewBox="0 0 200 50"
version="1.1"
id="svg8"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
sodipodi:docname="multifeeder.svg">
<defs
id="defs2">
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter863"
x="-6.5066022e-06"
width="1.000013"
y="-3.1750932e-05"
height="1.0000635">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.00051484815"
id="feGaussianBlur865" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="362.93895"
inkscape:cy="176.11126"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
width="100mm"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:43.7437px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:4,4;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter863);stroke-linecap:round"
x="4.3744469"
y="43.628365"
id="text835"><tspan
sodipodi:role="line"
id="tspan833"
x="4.3744469"
y="43.628365"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:43.7437px;font-family:'UKIJ Tiken';-inkscape-font-specification:'UKIJ Tiken';fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:4,4;stroke-dashoffset:0;stroke-opacity:1;stroke-linecap:round">multifeeder</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

45
templates/index.html

@ -6,33 +6,52 @@
<link rel="stylesheet" type="text/css" href="/css/stylesheet.css"> <link rel="stylesheet" type="text/css" href="/css/stylesheet.css">
</head> </head>
<body> <body>
<h1>multifeeder</h1> <h1 id="title">
<img src="/img/multifeeder.svg">
</h1>
<div align="center">(<a href="https://git.vvvvvvaria.org/varia/multifeeder/src/branch/master/feeds.txt" target="_blank">Add a feed</a>)</div>
<div align="center">Currently feeding:</div>
<br>
<br>
<table> <table>
<tbody> <tbody>
{% for x, feed in feeds.items() %} {% for x, feed in db['feeds'].items() %}
<tr> <tr>
<td>{{ feed.title }}</td> <td class="title">{{ feed.title }}</td>
<td>{{ feed.link }}</td> <td class="link"><a href="{{ feed.link }}" target="_blank">{{ feed.link }}</a></td>
<td class="description">{{ feed.description }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<br>
<br>
<section id="api"> <section id="api">
<h2>API</h2> <div class="accesspoint">
<!-- <div class="accesspoint"> <h2>/API/latest/[num]</h2>
/API/latest/[num] For example: <a href="/API/latest/5" target="_blank">https://multi.vvvvvvaria.org/API/latest/5</a>
<br>
(for the latest 5 posts in all feeds)
<br><br> <br><br>
(not there yet) Format: JSON
</div> --> </div>
<div class="accesspoint"> <div class="accesspoint">
/API/today/ <h2>/API/today/</h2>
For example: <a href="/API/today/" target="_blank">https://multi.vvvvvvaria.org/API/today/</a>
<br>
(for the posts published today)
<br><br> <br><br>
For example: <a href="/API/today/" target="_blank">localhost:5678/API/today/</a> Format: JSON
</div> </div>
<div class="accesspoint"> <div class="accesspoint">
/API/past/[days] <h2>/API/past/[days]</h2>
For example: <a href="/API/past/30" target="_blank">https://multi.vvvvvvaria.org/API/past/30</a>
<br>
(for all the posts published in the last 30 days)
<br><br> <br><br>
For example: <a href="/API/past/30" target="_blank">localhost:5678/API/past/30</a> Format: JSON
</div> </div>
</section> </section>
</body> </body>

Loading…
Cancel
Save