Experimental atom feed for photos, albums, search.

This commit is contained in:
voussoir 2022-07-19 20:05:15 -07:00
parent 17e0d0b6a6
commit 2562084fce
No known key found for this signature in database
GPG key ID: 5F7554F8C26DACCB
3 changed files with 105 additions and 0 deletions

View file

@ -2,6 +2,7 @@
This file provides functions which are used in various places throughout the
codebase but don't deserve to be methods of any class.
'''
import bs4
import datetime
import hashlib
import mimetypes
@ -304,6 +305,28 @@ def is_xor(*args) -> bool:
'''
return [bool(a) for a in args].count(True) == 1
def make_atom_feed(objects, feed_title, feed_link, feed_id) -> bs4.BeautifulSoup:
soup = bs4.BeautifulSoup('', 'xml')
feed = soup.new_tag('feed')
soup.append(feed)
title = soup.new_tag('title')
title.string = feed_title
feed.append(title)
link = soup.new_tag('link')
link['href'] = feed_link
feed.append(link)
id_element = soup.new_tag('id')
id_element.string = feed_id
feed.append(id_element)
for obj in objects:
feed.append(obj.atomify())
return soup
def now():
'''
Return the current UTC datetime object.

View file

@ -4,6 +4,7 @@ but are returned by the PDB accesses.
'''
import abc
import bcrypt
import bs4
import datetime
import hashlib
import os
@ -418,6 +419,39 @@ class Album(ObjectBase, GroupableMixin):
for photo in photos:
photo.add_tag(tag)
def atomify(self) -> bs4.BeautifulSoup:
soup = bs4.BeautifulSoup('', 'xml')
entry = soup.new_tag('entry')
soup.append(entry)
id_element = soup.new_tag('id')
id_element.string = str(self.id)
entry.append(id_element)
title = soup.new_tag('title')
title.string = self.display_name
entry.append(title)
link = soup.new_tag('link')
link['rel'] = 'alternate'
link['type'] = 'text/html'
link['href'] = f'/album/{self.id}'
entry.append(link)
published = soup.new_tag('published')
published.string = self.created.isoformat()
entry.append(published)
content = soup.new_tag('content')
# content.string = bs4.CData(f'<img src="/thumbnail/{self.id}.jpg"/>')
entry.append(content)
typ = soup.new_tag('etiquette:type')
typ.string = 'album'
entry.append(typ)
return soup
@decorators.required_feature('album.edit')
@worms.atomic
def delete(self, *, delete_children=False) -> None:
@ -937,6 +971,39 @@ class Photo(ObjectBase):
return tag
def atomify(self) -> bs4.BeautifulSoup:
soup = bs4.BeautifulSoup('', 'xml')
entry = soup.new_tag('entry')
soup.append(entry)
id_element = soup.new_tag('id')
id_element.string = str(self.id)
entry.append(id_element)
title = soup.new_tag('title')
title.string = self.basename
entry.append(title)
link = soup.new_tag('link')
link['rel'] = 'alternate'
link['type'] = 'text/html'
link['href'] = f'/photo/{self.id}'
entry.append(link)
published = soup.new_tag('published')
published.string = self.created.isoformat()
entry.append(published)
content = soup.new_tag('content')
content.string = bs4.CData(f'<img src="/thumbnail/{self.id}.jpg"/>')
entry.append(content)
typ = soup.new_tag('etiquette:type')
typ.string = 'photo'
entry.append(typ)
return soup
@property
def basename(self) -> str:
return self.override_filename or self.real_path.basename

View file

@ -530,6 +530,21 @@ def get_search_html():
)
return response
@site.route('/search.atom')
def get_search_atom():
search_results = get_search_core()['results']
soup = etiquette.helpers.make_atom_feed(
search_results,
feed_id=request.query_string.decode('utf-8'),
feed_title='etiquette search',
feed_link=request.url.replace('/search.atom', '/search'),
)
outgoing_headers = {
'Content-Type': 'application/atom+xml; charset=utf-8',
}
response = flask.Response(str(soup), headers=outgoing_headers)
return response
@site.route('/search.json')
def get_search_json():
search_results = get_search_core()