2021-04-09 16:17:53 +02:00
|
|
|
import aiohttp
|
2021-04-17 23:05:32 +02:00
|
|
|
from aredis import StrictRedis
|
|
|
|
from ratelimit import RateLimitMiddleware, Rule
|
|
|
|
from ratelimit.auths.session import from_session
|
2021-04-09 16:17:53 +02:00
|
|
|
from starlette.applications import Starlette
|
2021-04-17 23:05:32 +02:00
|
|
|
from starlette.middleware import Middleware
|
|
|
|
from starlette.middleware.sessions import SessionMiddleware
|
2021-04-09 16:17:53 +02:00
|
|
|
from starlette.requests import Request
|
|
|
|
from starlette.responses import JSONResponse, Response
|
|
|
|
from starlette.routing import Route
|
2021-04-09 16:26:58 +02:00
|
|
|
from config import debug, user_agent, redis_socket
|
2021-04-08 22:29:27 +02:00
|
|
|
from hnapi import HNClient
|
|
|
|
from reader import Reader
|
2021-04-17 23:05:32 +02:00
|
|
|
from redis_backend import CustomRedisBackend
|
2021-04-08 22:29:27 +02:00
|
|
|
|
2021-04-09 16:17:53 +02:00
|
|
|
conn = aiohttp.TCPConnector(ttl_dns_cache=60 * 10)
|
2021-04-09 16:26:58 +02:00
|
|
|
session = aiohttp.ClientSession(connector=conn, headers={
|
|
|
|
"User-Agent": user_agent
|
|
|
|
})
|
|
|
|
if redis_socket:
|
2021-04-17 23:05:32 +02:00
|
|
|
r = StrictRedis(unix_socket_path=redis_socket)
|
2021-04-09 16:26:58 +02:00
|
|
|
else:
|
2021-04-17 23:05:32 +02:00
|
|
|
r = StrictRedis()
|
2021-04-09 16:17:53 +02:00
|
|
|
reader = Reader()
|
2021-04-08 22:29:27 +02:00
|
|
|
|
2021-04-09 16:17:53 +02:00
|
|
|
api = HNClient(session, r)
|
2021-04-08 22:29:27 +02:00
|
|
|
|
|
|
|
|
2021-04-09 16:17:53 +02:00
|
|
|
async def item(request: Request):
|
|
|
|
item_id = request.path_params["item_id"]
|
|
|
|
data = await api.get_full_item(item_id)
|
|
|
|
return JSONResponse(data)
|
2021-04-08 22:29:27 +02:00
|
|
|
|
|
|
|
|
2021-04-09 16:17:53 +02:00
|
|
|
async def read(request: Request):
|
2021-04-17 23:05:32 +02:00
|
|
|
print(request.session)
|
|
|
|
request.session.update({"a": "b"})
|
2021-04-09 16:17:53 +02:00
|
|
|
item_id = request.path_params["item_id"]
|
|
|
|
item = await api.get_item(item_id)
|
2021-04-08 22:29:27 +02:00
|
|
|
if "url" not in item:
|
|
|
|
return "Url not found", 404
|
|
|
|
key = f"hnclient_read_{item_id}"
|
|
|
|
|
2021-04-17 23:05:32 +02:00
|
|
|
cache = await r.get(key)
|
2021-04-08 22:29:27 +02:00
|
|
|
if cache:
|
2021-04-09 16:17:53 +02:00
|
|
|
response = Response(cache)
|
2021-04-08 22:29:27 +02:00
|
|
|
else:
|
2021-04-09 16:17:53 +02:00
|
|
|
output = await reader.readable_html(item["url"])
|
2021-04-17 23:05:32 +02:00
|
|
|
await r.set(key, output, ex=60 * 60 * 24)
|
2021-04-09 16:17:53 +02:00
|
|
|
response = Response(output)
|
|
|
|
response.media_type = "application/json"
|
2021-04-08 22:29:27 +02:00
|
|
|
return response
|
2021-04-09 16:17:53 +02:00
|
|
|
|
|
|
|
|
|
|
|
async def topstories(request: Request):
|
2021-04-09 17:40:24 +02:00
|
|
|
offset = int(request.query_params.get("offset", 0))
|
|
|
|
data = await api.get_stories("topstories", offset=offset)
|
2021-04-09 16:17:53 +02:00
|
|
|
return JSONResponse(data)
|
|
|
|
|
|
|
|
|
|
|
|
app = Starlette(debug=debug, routes=[
|
|
|
|
Route('/api/item/{item_id:int}', item),
|
|
|
|
Route('/api/read/{item_id:int}', read),
|
|
|
|
Route('/api/topstories', topstories),
|
|
|
|
])
|
2021-04-17 23:05:32 +02:00
|
|
|
|
|
|
|
if not debug:
|
|
|
|
app.add_middleware(
|
|
|
|
RateLimitMiddleware,
|
|
|
|
authenticate=from_session,
|
|
|
|
backend=CustomRedisBackend(r),
|
|
|
|
config={
|
|
|
|
r"^/api/": [Rule(minute=4)],
|
|
|
|
},
|
|
|
|
)
|