47 lines
1.3 KiB
Python
47 lines
1.3 KiB
Python
from datetime import datetime
|
|
|
|
import dateutil.parser
|
|
import httpx
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class Story(BaseModel):
|
|
"""Model representing a Hacker News story."""
|
|
|
|
id: str
|
|
title: str = Field(description="Title of the story.")
|
|
url: str | None = Field(description="URL of the story.")
|
|
|
|
created_at: datetime
|
|
|
|
|
|
class HackerNewsClient:
|
|
def __init__(self, client: httpx.Client | None = None):
|
|
base_url = "https://hn.algolia.com/api/v1"
|
|
if client:
|
|
client.base_url = base_url
|
|
self._client = client
|
|
else:
|
|
self._client = httpx.Client(base_url=base_url)
|
|
|
|
def get_top_stories(self, limit: int = 10) -> list[Story]:
|
|
resp = self._client.get(
|
|
"search",
|
|
params={"tags": "front_page", "hitsPerPage": limit, "page": 0},
|
|
)
|
|
resp.raise_for_status()
|
|
return [
|
|
Story(
|
|
id=hit["objectID"],
|
|
title=hit["title"],
|
|
url=hit.get("url"),
|
|
created_at=dateutil.parser.isoparse(hit["created_at"]),
|
|
)
|
|
for hit in resp.json().get("hits", [])
|
|
]
|
|
|
|
def get_item(self, item_id):
|
|
resp = self._client.get(f"items/{item_id}")
|
|
resp.raise_for_status()
|
|
return resp.json()
|