73 lines
2.4 KiB
Python
73 lines
2.4 KiB
Python
from contextlib import asynccontextmanager
|
|
from datetime import datetime, timezone
|
|
from os import environ
|
|
|
|
import asyncpraw
|
|
from async_lru import alru_cache
|
|
from fastapi import FastAPI, Response, HTTPException
|
|
from feedgen.feed import FeedGenerator
|
|
|
|
|
|
REDDIT_CLIENT_ID = environ["REDDIT_CLIENT_ID"]
|
|
REDDIT_CLIENT_SECRET = environ["REDDIT_CLIENT_SECRET"]
|
|
REDDIT_PASSWORD = environ["REDDIT_PASSWORD"]
|
|
REDDIT_USERNAME = environ["REDDIT_USERNAME"]
|
|
RSS_HOST = environ["RSS_HOST"]
|
|
|
|
|
|
@alru_cache(ttl=15 * 60)
|
|
async def fetch(feed, comments):
|
|
fg = FeedGenerator()
|
|
fg.id(f'{RSS_HOST}/{feed}')
|
|
fg.title(f'r/{feed}')
|
|
fg.link(href=f'{RSS_HOST}/{feed}')
|
|
fg.description(f'r/{feed}')
|
|
|
|
client = asyncpraw.Reddit(
|
|
user_agent="stuff",
|
|
client_id=REDDIT_CLIENT_ID,
|
|
client_secret=REDDIT_CLIENT_SECRET,
|
|
username=REDDIT_USERNAME,
|
|
password=REDDIT_PASSWORD,
|
|
)
|
|
|
|
async with client as reddit:
|
|
subreddit = await reddit.subreddit(feed)
|
|
async for submission in subreddit.top(limit=30, time_filter="week"):
|
|
if submission.selftext == "":
|
|
continue
|
|
|
|
fe = fg.add_entry()
|
|
fe.id(submission.id)
|
|
fe.title(submission.title)
|
|
fe.link(href=submission.url)
|
|
fe.pubDate(datetime.fromtimestamp(submission.created_utc, timezone.utc))
|
|
author = 'none' if submission.author is None else submission.author.name
|
|
content = f"<p>{author} ({submission.score})</p>"
|
|
content += f"<p>{submission.selftext_html}</p>"
|
|
if comments:
|
|
comments = ""
|
|
for comment in await submission.comments():
|
|
if isinstance(comment, asyncpraw.models.MoreComments):
|
|
continue
|
|
if comment.author is None:
|
|
continue
|
|
author = comment.author.name
|
|
if author.lower() == 'automoderator':
|
|
continue
|
|
comments += f"<li>{author} ({comment.score}) {comment.body_html}"
|
|
content += f"<ul>{comments}</ul>"
|
|
|
|
fe.content(content)
|
|
|
|
rss = fg.rss_str(pretty=True)
|
|
return rss
|
|
|
|
|
|
app = FastAPI()
|
|
|
|
|
|
@app.get("/{feed}")
|
|
async def root(feed: str, comments: bool = False):
|
|
rss = await fetch(feed, comments)
|
|
return Response(content=rss, media_type="application/xml")
|