103 lines
3.8 KiB
Python
103 lines
3.8 KiB
Python
# [[file:../arcology-feedgen.org::*Invoking Pandoc for the Feed Generator][Invoking Pandoc for the Feed Generator:1]]
|
|
import re
|
|
from fastapi import Response, HTTPException
|
|
|
|
import asyncio
|
|
from sqlmodel import Session
|
|
from async_lru import alru_cache
|
|
from typing import Optional
|
|
|
|
from arcology.html import rewrite_html
|
|
from arcology.key import ArcologyKey
|
|
from arcology.parse import parse_sexp, print_sexp
|
|
from arcology.arroyo import Page
|
|
# Invoking Pandoc for the Feed Generator:1 ends here
|
|
|
|
# [[file:../arcology-feedgen.org::*Invoking Pandoc for the Feed Generator][Invoking Pandoc for the Feed Generator:2]]
|
|
class ExportException(BaseException):
|
|
code: int
|
|
stderr: str
|
|
|
|
def __init__(self, code, stderr=None):
|
|
self.code = code
|
|
self.stderr = stderr
|
|
|
|
@alru_cache(maxsize=64)
|
|
async def export_pandoc(file: str, hash: str) -> str:
|
|
proc = await asyncio.create_subprocess_shell(
|
|
f"pandoc {file} --lua-filter=./arcology/pandoc/make-atom.lua --template=./arcology/pandoc/atom.xml -s",
|
|
stdout=asyncio.subprocess.PIPE,
|
|
stderr=asyncio.subprocess.PIPE)
|
|
stdout, stderr = await proc.communicate()
|
|
if proc.returncode == 0:
|
|
return stdout.decode()
|
|
else:
|
|
raise ExportException(code=proc.returncode, stderr=stderr.decode())
|
|
|
|
async def render_feed_from_file(_request, file: str, engine, site) -> Optional[Response]:
|
|
with Session(engine) as session:
|
|
p = Page.from_file(file, session)
|
|
if p is None:
|
|
raise HTTPException(status_code=404, detail="Feed not found.")
|
|
try:
|
|
xml = await export_pandoc(file, p.hash)
|
|
except ExportException as e:
|
|
raise HTTPException(status_code=500, detail=f"pandoc exited {e.code} w/ {e.stderr}")
|
|
|
|
return hydrate_feed(file, xml, session)
|
|
# Invoking Pandoc for the Feed Generator:2 ends here
|
|
|
|
# [[file:../arcology-feedgen.org::*Invoking Pandoc for the Feed Generator][Invoking Pandoc for the Feed Generator:3]]
|
|
def hydrate_feed(filename: str, xml: str, session) -> str:
|
|
page = Page.from_file(filename, session)
|
|
def feed_page_replacement_fn(match):
|
|
return page.get_file()
|
|
|
|
akey = ArcologyKey(page.get_key())
|
|
|
|
out_xml = xml
|
|
out_xml = re.sub(r'{ARCOLOGY_FEED_PAGE}', akey.to_url(), out_xml)
|
|
out_xml = rewrite_html(out_xml, session) # lol dangerous
|
|
return out_xml
|
|
# Invoking Pandoc for the Feed Generator:3 ends here
|
|
|
|
# [[file:../arcology-feedgen.org::*Listing the Arcology Feeds][Listing the Arcology Feeds:1]]
|
|
from typing import List
|
|
|
|
from sqlmodel import select, Session
|
|
|
|
from arcology.arroyo import Keyword
|
|
from arcology.parse import parse_sexp
|
|
from arcology.key import ArcologyKey
|
|
# Listing the Arcology Feeds:1 ends here
|
|
|
|
# [[file:../arcology-feedgen.org::*Listing the Arcology Feeds][Listing the Arcology Feeds:2]]
|
|
def arcology_feed_q():
|
|
return select(Keyword).where(Keyword.keyword=='"ARCOLOGY_FEED"')
|
|
|
|
def get_feed_keys(session) -> List[str]:
|
|
return [parse_sexp(row.value) for row in session.exec(arcology_feed_q())]
|
|
|
|
def get_feed_files(session) -> List[str]:
|
|
return [parse_sexp(row.file) for row in session.exec(arcology_feed_q())]
|
|
# Listing the Arcology Feeds:2 ends here
|
|
|
|
# [[file:../arcology-feedgen.org::*Listing the Arcology Feeds][Listing the Arcology Feeds:5]]
|
|
def make_feed_entries(site_key: str, session):
|
|
|
|
feed_page_titles = dict() # file -> title
|
|
for feed_file in get_feed_files(session):
|
|
p = Page.from_file(feed_file, session)
|
|
if p.get_site().key == site_key:
|
|
feed_page_titles[feed_file] = p.get_title()
|
|
|
|
ret = list()
|
|
for feed_key in get_feed_keys(session):
|
|
feed_url = ArcologyKey(feed_key).to_url()
|
|
feed_file = Keyword.get("ARCOLOGY_FEED", feed_key, session=session).filename()
|
|
if feed_page_titles.get(feed_file, None):
|
|
ret.append((feed_url, feed_page_titles[feed_file]))
|
|
|
|
return ret
|
|
# Listing the Arcology Feeds:5 ends here
|