afpy.org/data_xml.py

180 lines
5.5 KiB
Python
Raw Normal View History

2018-10-04 13:34:38 +00:00
import email
from pathlib import Path
2020-01-06 22:01:16 +00:00
import time
2018-10-04 13:34:38 +00:00
from xml.etree import ElementTree
2020-01-06 22:01:16 +00:00
from werkzeug.utils import secure_filename
2018-10-04 13:34:38 +00:00
POST_ACTUALITIES = 'actualites'
POST_JOBS = 'emplois'
POSTS = {POST_ACTUALITIES: "Actualités", POST_JOBS: "Offres demploi"}
STATE_WAITING = 'waiting'
STATE_PUBLISHED = 'published'
2018-10-04 15:48:45 +00:00
STATE_TRASHED = 'trashed'
2018-10-04 15:53:55 +00:00
STATES = {
STATE_WAITING: "En attente",
STATE_PUBLISHED: "Publié",
STATE_TRASHED: "À la corbeille"
}
2018-10-04 13:34:38 +00:00
ACTION_PUBLISH = 'publish'
ACTION_UNPUBLISH = 'unpublish'
2018-10-04 15:53:55 +00:00
ACTION_REPUBLISH = 'republish'
ACTION_TRASH = 'trash'
ACTION_EDIT = 'edit'
ACTION_DELETE_IMAGE = 'delete_image'
2018-10-04 15:53:55 +00:00
ACTIONS = {
ACTION_PUBLISH: "Publier",
ACTION_UNPUBLISH: "Dépublier",
ACTION_REPUBLISH: "Republier",
ACTION_TRASH: "Supprimer",
ACTION_EDIT: 'Editer',
ACTION_DELETE_IMAGE: "Supprimer l'image"
2018-10-04 15:53:55 +00:00
}
2018-10-04 13:34:38 +00:00
2018-10-04 15:44:18 +00:00
IMAGE = '_image'
2018-10-04 13:34:38 +00:00
TIMESTAMP = '_timestamp'
STATE = '_state'
PATH = '_path'
DIR = '_dir'
BASE_DIR = 'posts'
BASE_FILE = 'post.xml'
2018-10-04 15:44:18 +00:00
BASE_IMAGE = 'post.jpg'
2018-10-04 13:34:38 +00:00
class DataException(Exception):
def __init__(self, *args, http_code=None, **kwargs):
self.http_code = http_code
super().__init__(*args, **kwargs)
root = Path(__file__).parent / BASE_DIR
for category in POSTS:
for state in STATES:
(root / category / state).mkdir(parents=True, exist_ok=True)
def get_path(category, state, timestamp, *args, create_dir=False):
path = root / category / state / timestamp
if create_dir:
path.mkdir(exist_ok=True)
for arg in args:
path /= arg
return path
def count_posts(category, state=STATE_PUBLISHED):
return len(tuple((root / category / state).iterdir()))
def get_posts(category, state=STATE_PUBLISHED, start=0, end=None):
path = root / category / state
timestamps = sorted(path.iterdir(), reverse=True)
timestamps = timestamps[start:end] if end else timestamps[start:]
for timestamp in timestamps:
2020-01-06 21:09:24 +00:00
post = get_post(category, timestamp.name, state)
if post:
yield post
2018-10-04 13:34:38 +00:00
def get_post(category, timestamp, states=None):
states = (
states
if isinstance(states, (tuple, list))
else [states]
if isinstance(states, str)
else STATES
)
for state in states:
dir = root / category / state / timestamp
path = dir / BASE_FILE
if path.is_file():
break
else:
return None
tree = ElementTree.parse(path)
post = {item.tag: (item.text or '').strip() for item in tree.iter()}
2018-10-04 15:44:18 +00:00
# Calculated fields
image = post.get('image') or BASE_IMAGE
if (dir / image).is_file():
post[IMAGE] = '/'.join((category, state, timestamp, image))
post[TIMESTAMP] = timestamp
2018-10-04 13:34:38 +00:00
post[STATE] = state
post[DIR] = dir
post[PATH] = path
return post
2018-10-04 15:34:58 +00:00
def save_post(category, timestamp, admin, form, files):
2018-10-04 13:34:38 +00:00
if timestamp is None:
status = STATE_WAITING
timestamp = str(int(time.time()))
elif get_path(category, STATE_WAITING, timestamp, BASE_FILE).is_file():
status = STATE_WAITING
elif get_path(category, STATE_PUBLISHED, timestamp, BASE_FILE).is_file():
status = STATE_PUBLISHED
2018-10-04 15:53:55 +00:00
elif get_path(category, STATE_TRASHED, timestamp, BASE_FILE).is_file():
status = STATE_TRASHED
2018-10-04 13:34:38 +00:00
else:
raise DataException(http_code=404)
if status == STATE_TRASHED and not admin:
2018-10-04 13:34:38 +00:00
raise DataException(http_code=401)
post = get_path(category, status, timestamp, BASE_FILE, create_dir=True)
tree = ElementTree.Element('entry')
2018-10-04 15:35:16 +00:00
2018-10-04 13:34:38 +00:00
for key, value in form.items():
if key.startswith('_'):
continue
element = ElementTree.SubElement(tree, key)
element.text = value
2018-10-05 10:38:25 +00:00
2018-10-05 14:44:39 +00:00
if '_image_path' in form:
2018-10-05 14:36:51 +00:00
image_path = root / form['_image_path']
if ACTION_DELETE_IMAGE in form and image_path.exists():
2018-10-05 14:36:51 +00:00
image_path.unlink()
else:
if 'image' in files and files['image'].filename:
post_image = files['image']
filename = secure_filename(post_image.filename)
post_image.save(str(post.parent / filename))
element = ElementTree.SubElement(tree, 'image')
element.text = filename
elif '_image_path' in form:
2018-10-05 14:44:39 +00:00
element = ElementTree.SubElement(tree, 'image')
element.text = image_path.name
2018-10-04 13:34:38 +00:00
element = ElementTree.SubElement(tree, STATE_PUBLISHED)
element.text = email.utils.formatdate(
int(timestamp) if timestamp else time.time()
)
ElementTree.ElementTree(tree).write(post)
2018-10-04 16:16:23 +00:00
if ACTION_TRASH in form and status == STATE_PUBLISHED:
(root / category / STATE_PUBLISHED / timestamp).rename(
root / category / STATE_TRASHED / timestamp
)
if not admin and ACTION_EDIT in form and status == STATE_PUBLISHED:
(root / category / STATE_PUBLISHED / timestamp).rename(
root / category / STATE_WAITING / timestamp
)
2018-10-04 16:16:23 +00:00
2018-10-04 13:34:38 +00:00
if admin:
if ACTION_PUBLISH in form and status == STATE_WAITING:
(root / category / STATE_WAITING / timestamp).rename(
root / category / STATE_PUBLISHED / timestamp
)
elif ACTION_UNPUBLISH in form and status == STATE_PUBLISHED:
(root / category / STATE_PUBLISHED / timestamp).rename(
root / category / STATE_WAITING / timestamp
)
2018-10-04 15:53:55 +00:00
elif ACTION_REPUBLISH in form and status == STATE_TRASHED:
(root / category / STATE_TRASHED / timestamp).rename(
root / category / STATE_PUBLISHED / timestamp
)
2018-10-04 13:34:38 +00:00
return get_post(category, timestamp)