deps and autoformat

This commit is contained in:
cellarspoon
2021-12-15 11:41:35 +01:00
parent 95964862b7
commit be3e14ac6c
16 changed files with 610 additions and 387 deletions

View File

@ -1,9 +0,0 @@
# Calendar Feed
Generate HUGO posts based on a publicly accessible ICS calendar.
## Use
Fill in your details in `calendar_feed_config.py`
## TODO / FIXME
* Multiple calendars to multiple hugo categories

View File

@ -1,49 +1,52 @@
#!/bin/python3
#lumbung.space calendar feed generator
#© 2021 roel roscam abbing gplv3 etc
# lumbung.space calendar feed generator
# © 2021 roel roscam abbing gplv3 etc
from ics import Calendar
import requests
import jinja2
import os
import shutil
from slugify import slugify
from natural import date
from event_feed_config import calendar_url, output_dir
from urllib.parse import urlparse
import arrow
import re
import shutil
from urllib.parse import urlparse
import arrow
import jinja2
import requests
from ics import Calendar
from natural import date
from slugify import slugify
from event_feed_config import calendar_url, output_dir
cal = Calendar(requests.get(calendar_url).text)
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.curdir)
)
env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.curdir))
if not os.path.exists(output_dir):
os.mkdir(output_dir)
template = env.get_template('event_template.md')
template = env.get_template("event_template.md")
existing_posts = os.listdir(output_dir)
def findURLs(string):
"""
return all URLs in a given string
"""
regex = r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))"
url = re.findall(regex,string)
return [x[0] for x in url]
url = re.findall(regex, string)
return [x[0] for x in url]
def find_imageURLS(string):
"""
return all image URLS in a given string
"""
regex = r"(?:http\:|https\:)?\/\/.*?\.(?:png|jpg|jpeg|gif|svg)"
regex = r"(?:http\:|https\:)?\/\/.*?\.(?:png|jpg|jpeg|gif|svg)"
img_urls = re.findall(regex, string, flags=re.IGNORECASE)
return img_urls
return img_urls
def create_metadata(event):
"""
@ -55,24 +58,28 @@ def create_metadata(event):
if location_urls:
location_url = location_urls[0]
event.location = '[{}]({})'.format(urlparse(location_url).netloc, location_url)
event.location = "[{}]({})".format(
urlparse(location_url).netloc, location_url
)
event_metadata = {
'name':event.name,
'created':event.created.format(),
'description': event.description,
'localized_begin': '           '.join(localize_time(event.begin)), #non-breaking space characters to defeat markdown
'begin': event.begin.format(),
'end': event.end.format(),
'duration': date.compress(event.duration),
'location': event.location,
'uid': event.uid,
'images' : find_imageURLS(event.description) # currently not used in template
"name": event.name,
"created": event.created.format(),
"description": event.description,
"localized_begin": "           ".join(
localize_time(event.begin)
), # non-breaking space characters to defeat markdown
"begin": event.begin.format(),
"end": event.end.format(),
"duration": date.compress(event.duration),
"location": event.location,
"uid": event.uid,
"images": find_imageURLS(event.description), # currently not used in template
}
return event_metadata
def localize_time(date):
"""
Turn a given date into various timezones
@ -82,28 +89,27 @@ def localize_time(date):
# 3 PM Kassel, Germany, 4 PM Ramallah/Jerusalem, Palestina (QoF),
# 8 AM Bogota, Colombia (MaMa), 8 PM Jakarta, Indonesia (Gudskul),
# 1 PM (+1day) Wellington, New Zealand (Fafswag), 9 AM Havana, Cuba (Instar).
tzs = [
('Kassel','Europe/Berlin'),
('Bamako', 'Europe/London'),
('Palestine','Asia/Jerusalem'),
('Bogota','America/Bogota'),
('Jakarta','Asia/Jakarta'),
('Makassar','Asia/Makassar'),
('Wellington', 'Pacific/Auckland')
]
("Kassel", "Europe/Berlin"),
("Bamako", "Europe/London"),
("Palestine", "Asia/Jerusalem"),
("Bogota", "America/Bogota"),
("Jakarta", "Asia/Jakarta"),
("Makassar", "Asia/Makassar"),
("Wellington", "Pacific/Auckland"),
]
localized_begins =[]
localized_begins = []
for location, tz in tzs:
localized_begins.append( #javascript formatting because of string creation from hell
'__{}__ {}'.format(
str(location),
str(date.to(tz).format("YYYY-MM-DD __HH:mm__"))
)
localized_begins.append( # javascript formatting because of string creation from hell
"__{}__ {}".format(
str(location), str(date.to(tz).format("YYYY-MM-DD __HH:mm__"))
)
)
return localized_begins
def create_event_post(post_dir, event):
"""
Create HUGO post based on calendar event metadata
@ -112,83 +118,86 @@ def create_event_post(post_dir, event):
In that case it will also delete images no longer in metadata
TODO: split this up into more functions for legibility
"""
if not os.path.exists(post_dir):
os.mkdir(post_dir)
event_metadata = create_metadata(event)
#list already existing images
#so we can later delete them if we dont find them in the event metadata anymore
# list already existing images
# so we can later delete them if we dont find them in the event metadata anymore
existing_images = os.listdir(post_dir)
try:
existing_images.remove('index.md')
existing_images.remove('.timestamp')
existing_images.remove("index.md")
existing_images.remove(".timestamp")
except:
pass
for img in event_metadata['images']:
for img in event_metadata["images"]:
# parse img url to safe local image name
img_name = img.split("/")[-1]
fn, ext = img_name.split(".")
img_name = slugify(fn) + "." + ext
#parse img url to safe local image name
img_name = img.split('/')[-1]
fn, ext = img_name.split('.')
img_name = slugify(fn) + '.' + ext
local_image = os.path.join(post_dir, img_name)
if not os.path.exists(local_image):
#download preview image
# download preview image
response = requests.get(img, stream=True)
with open(local_image, 'wb') as img_file:
with open(local_image, "wb") as img_file:
shutil.copyfileobj(response.raw, img_file)
print('Downloaded image for event "{}"'.format(event.name))
event_metadata['description'] = event_metadata['description'].replace(img, '![]({})'.format(img_name))
event_metadata["description"] = event_metadata["description"].replace(
img, "![]({})".format(img_name)
)
if img_name in existing_images:
existing_images.remove(img_name)
for left_over_image in existing_images:
#remove images we found, but which are no longer in remote event
os.remove(os.path.join(post_dir,left_over_image))
print('deleted image', left_over_image)
# remove images we found, but which are no longer in remote event
os.remove(os.path.join(post_dir, left_over_image))
print("deleted image", left_over_image)
with open(os.path.join(post_dir,'index.md'),'w') as f:
post = template.render(event = event_metadata)
with open(os.path.join(post_dir, "index.md"), "w") as f:
post = template.render(event=event_metadata)
f.write(post)
print('created post for', event.name, '({})'.format(event.uid))
print("created post for", event.name, "({})".format(event.uid))
with open(os.path.join(post_dir,'.timestamp'),'w') as f:
f.write(event_metadata['created'])
with open(os.path.join(post_dir, ".timestamp"), "w") as f:
f.write(event_metadata["created"])
def update_event_post(post_dir, event):
"""
Update a post based on the VCARD event 'created' field which changes when updated
"""
"""
if os.path.exists(post_dir):
old_timestamp = open(os.path.join(post_dir,'.timestamp')).read()
old_timestamp = open(os.path.join(post_dir, ".timestamp")).read()
if event.created > arrow.get(old_timestamp):
print('Updating', event.name, '({})'.format(event.uid))
print("Updating", event.name, "({})".format(event.uid))
create_event_post(post_dir, event)
else:
print('Event current: ', event.name, '({})'.format(event.uid))
print("Event current: ", event.name, "({})".format(event.uid))
for event in list(cal.events):
post_dir = os.path.join(output_dir, event.uid)
if event.uid not in existing_posts:
#if there is an event we dont already have, make it
if event.uid not in existing_posts:
# if there is an event we dont already have, make it
create_event_post(post_dir, event)
elif event.uid in existing_posts:
#if we already have it, update
elif event.uid in existing_posts:
# if we already have it, update
update_event_post(post_dir, event)
existing_posts.remove(event.uid) # create list of posts which have not been returned by the calendar
for post in existing_posts:
#remove events not returned by the calendar (deletion)
print('deleted', post)
shutil.rmtree(os.path.join(output_dir,post))
existing_posts.remove(
event.uid
) # create list of posts which have not been returned by the calendar
for post in existing_posts:
# remove events not returned by the calendar (deletion)
print("deleted", post)
shutil.rmtree(os.path.join(output_dir, post))

View File

@ -11,9 +11,8 @@ uid: "{{ event.uid }}"
{% if event.location %}
location: "{{ event.location }}"
{% endif %}
---
{% if event.description %}
{{ event.description }}

View File

@ -1,16 +0,0 @@
# Automatically generated by https://github.com/damnever/pigar.
# calendar-feed/event_feed.py: 3
Jinja2 == 2.10
# calendar-feed/event_feed.py: 1
ics == 0.7
# calendar-feed/event_feed.py: 6
natural == 0.2.0
# calendar-feed/event_feed.py: 5
python_slugify == 5.0.2
# calendar-feed/event_feed.py: 2
requests == 2.21.0