Skip to content

Commit

Permalink
v2.4.0 (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
c3kay authored Dec 7, 2024
2 parents 0816aa9 + 93269b1 commit 330e35b
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 97 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Publish
name: Build

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![PyPI](https://img.shields.io/pypi/v/hoyolab-rss-feeds)](https://pypi.org/project/hoyolab-rss-feeds/)
[![Python Version](https://img.shields.io/pypi/pyversions/hoyolab-rss-feeds)](https://pypi.org/project/hoyolab-rss-feeds/)
[![Tests Status](https://img.shields.io/github/actions/workflow/status/c3kay/hoyolab-rss-feeds/test.yaml?branch=master)](https://github.com/c3kay/hoyolab-rss-feeds/actions/workflows/test.yaml)
[![Tests Status](https://img.shields.io/github/actions/workflow/status/c3kay/hoyolab-rss-feeds/build.yaml)](https://github.com/c3kay/hoyolab-rss-feeds/actions/workflows/build.yaml)
[![Codecov](https://img.shields.io/codecov/c/gh/c3kay/hoyolab-rss-feeds/master)](https://app.codecov.io/gh/c3kay/hoyolab-rss-feeds)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)
Expand Down
5 changes: 2 additions & 3 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
## Changes

- Added support for python 3.12
- Support for python 3.8 will be dropped in the next version
- Added a `summary` field for feed items in both Atom and JSON-Feed format (#15)

## Fixes

- Added fix for native hoyolab video posts (#13)
- Updated dependencies
14 changes: 7 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["setuptools == 70.2.0", "setuptools_scm[toml] == 8.1.0"]
requires = ["setuptools == 75.6.0", "setuptools_scm[toml] == 8.1.0"]
build-backend = "setuptools.build_meta"

[project]
Expand All @@ -8,7 +8,7 @@ authors = [{name = "c3kay"}]
description = "RSS feed generator for official game news from Hoyolab."
readme = "README.md"
license = {text = "MIT License"}
requires-python = ">=3.8"
requires-python = ">=3.9"
keywords = [
"hoyolab",
"rss",
Expand Down Expand Up @@ -36,17 +36,17 @@ classifiers = [
dependencies = [
"aiohttp == 3.9.5",
"aiofiles == 24.1.0",
"pydantic == 1.10.13, < 2",
"pydantic >= 1.10.0, < 2",
'tomli == 2.0.1 ; python_version < "3.11"'
]
dynamic = ["version"]

[project.optional-dependencies]
dev = [
"tox == 4.11.4",
"pytest == 8.2.2",
"pytest-asyncio == 0.23.7",
"pytest-cov == 5.0.0",
"tox == 4.23.2",
"pytest == 8.3.4",
"pytest-asyncio == 0.24.0",
"pytest-cov == 6.0.0",
"pytest-mock == 3.14.0",
"atoma == 0.0.17",
"langdetect == 1.0.9"
Expand Down
1 change: 1 addition & 0 deletions src/hoyolabrssfeeds/hoyolab.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ async def get_feed_item(
"title": post["post"]["subject"],
"author": post["user"]["nickname"],
"content": post["post"]["content"],
"summary": post["post"]["desc"],
"category": post["post"]["official_type"],
"published": post["post"]["created_at"],
}
Expand Down
152 changes: 75 additions & 77 deletions src/hoyolabrssfeeds/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,40 +81,39 @@ class JSONFeedFileLoader(AbstractFeedFileLoader):
async def get_feed_items(self) -> List[FeedItem]:
"""Returns feed items of JSON-Feed if feed exists."""

if self.config.path.exists():
feed_items = []
feed = await self._load_from_file()
if not self.config.path.exists():
return []

try:
for item in feed["items"]:
category = FeedItemCategory.from_str(item["tags"][0])

item_dict = {
"id": item["id"],
"title": item["title"],
"author": item["authors"][0]["name"],
"content": item["content_html"],
"category": category,
"published": item["date_published"],
}

if "date_modified" in item:
item_dict["updated"] = item["date_modified"]

if "image" in item:
item_dict["image"] = item["image"]

feed_items.append(item_dict)
except KeyError as err:
raise FeedFormatError(
"Could not find required key in JSON feed!"
) from err
except ValueError as err:
raise FeedFormatError("Could not load JSON feed items!") from err
feed_items = []
feed = await self._load_from_file()

return pydantic.parse_obj_as(List[FeedItem], feed_items)
else:
return []
try:
for item in feed["items"]:
category = FeedItemCategory.from_str(item["tags"][0])

item_dict = {
"id": item["id"],
"title": item["title"],
"author": item["authors"][0]["name"],
"content": item["content_html"],
"summary": item["summary"],
"category": category,
"published": item["date_published"],
}

if "date_modified" in item:
item_dict["updated"] = item["date_modified"]

if "image" in item:
item_dict["image"] = item["image"]

feed_items.append(item_dict)
except KeyError as err:
raise FeedFormatError("Could not find required key in JSON feed!") from err
except ValueError as err:
raise FeedFormatError("Could not load JSON feed items!") from err

return pydantic.parse_obj_as(List[FeedItem], feed_items)

async def _load_from_file(self) -> Dict[str, Any]:
"""Load JSON-Feed from file."""
Expand All @@ -140,56 +139,55 @@ class AtomFeedFileLoader(AbstractFeedFileLoader):
async def get_feed_items(self) -> List[FeedItem]:
"""Returns feed items of Atom feed if feed exists."""

if self.config.path.exists():
feed_items = []
root = await self._load_from_file()

for entry in root.findall("entry"):
id_str = entry.findtext("id")
item_id = id_str.rpartition(":")[2] if id_str is not None else None

category_node = entry.find("category")
try:
category = (
FeedItemCategory.from_str(category_node.get("term", default=""))
if category_node is not None
else None
)
except ValueError as err:
raise FeedFormatError("Could not load Atom feed entries!") from err

published_str = entry.findtext("published")
published = (
datetime.fromisoformat(published_str)
if published_str is not None
else None
)

updated_str = entry.findtext("updated")
updated = (
datetime.fromisoformat(updated_str)
if updated_str is not None
else None
)
if not self.config.path.exists():
return []

item_dict = {
"id": item_id,
"title": entry.findtext("title"),
"author": entry.findtext("author/name"),
"content": entry.findtext("content"),
"category": category,
"published": published,
"updated": updated,
}
feed_items = []
root = await self._load_from_file()

feed_items.append(item_dict)
for entry in root.findall("entry"):
id_str = entry.findtext("id")
item_id = id_str.rpartition(":")[2] if id_str is not None else None

category_node = entry.find("category")
try:
return pydantic.parse_obj_as(List[FeedItem], feed_items)
except pydantic.ValidationError as err:
category = (
FeedItemCategory.from_str(category_node.get("term", default=""))
if category_node is not None
else None
)
except ValueError as err:
raise FeedFormatError("Could not load Atom feed entries!") from err
else:
return []

published_str = entry.findtext("published")
published = (
datetime.fromisoformat(published_str)
if published_str is not None
else None
)

updated_str = entry.findtext("updated")
updated = (
datetime.fromisoformat(updated_str) if updated_str is not None else None
)

item_dict = {
"id": item_id,
"title": entry.findtext("title"),
"author": entry.findtext("author/name"),
"content": entry.findtext("content"),
"summary": entry.findtext("summary"),
"category": category,
"published": published,
"updated": updated,
}

feed_items.append(item_dict)

try:
return pydantic.parse_obj_as(List[FeedItem], feed_items)
except pydantic.ValidationError as err:
raise FeedFormatError("Could not load Atom feed entries!") from err

async def _load_from_file(self) -> ElementTree.Element:
"""Load Atom feed from file."""
Expand Down
1 change: 1 addition & 0 deletions src/hoyolabrssfeeds/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class FeedItem(MyBaseModel):
title: str
author: str
content: str
summary: str
category: FeedItemCategory
published: datetime
updated: Optional[datetime] = None
Expand Down
3 changes: 3 additions & 0 deletions src/hoyolabrssfeeds/writers.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def create_json_feed_item(item: FeedItem) -> Dict[str, Any]:
"authors": [{"name": item.author}],
"tags": [item.category.name.title()],
"content_html": item.content,
"summary": item.summary,
"date_published": item.published.astimezone().isoformat(),
}

Expand Down Expand Up @@ -211,6 +212,8 @@ def create_atom_feed_entries(
item.content
)

ElementTree.SubElement(entry, "summary").text = item.summary

entries.append(entry)

return entries
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ def feed_item() -> models.FeedItem:
title="Test Article",
author="John Doe",
content="<p>Hello World!</p>",
summary="Hello!",
category=models.FeedItemCategory.INFO,
published=datetime(2022, 10, 3, 16).astimezone(),
updated=datetime(2022, 10, 3, 18).astimezone(),
Expand All @@ -190,6 +191,7 @@ def json_feed_items(feed_item_list: List[models.FeedItem]) -> Dict[str, Any]:
"authors": [{"name": feed_item.author}],
"tags": [feed_item.category.name.title()],
"content_html": feed_item.content,
"summary": feed_item.summary,
"date_published": feed_item.published.astimezone().isoformat(),
"date_modified": (
feed_item.updated.astimezone().isoformat()
Expand Down Expand Up @@ -218,6 +220,7 @@ def atom_feed_entries(feed_item_list: List[models.FeedItem]) -> ElementTree.Elem

ElementTree.SubElement(entry, "title").text = feed_item.title
ElementTree.SubElement(entry, "content").text = feed_item.content
ElementTree.SubElement(entry, "summary").text = feed_item.summary
ElementTree.SubElement(
entry, "category", {"term": feed_item.category.name.title()}
)
Expand Down Expand Up @@ -315,6 +318,9 @@ def validate_hoyolab_post(post: Dict[str, Any], is_full_post: bool) -> None:
assert type(post["post"]["content"]) is str
assert len(post["post"]["content"]) > 0

assert type(post["post"]["desc"]) is str
assert len(post["post"]["desc"]) > 0

assert type(post["post"]["structured_content"]) is str
assert len(post["post"]["structured_content"]) > 0

Expand Down
1 change: 1 addition & 0 deletions tests/test_hoyolab.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ async def test_get_feed_item(
"post_id": str(feed_item.id),
"subject": feed_item.title,
"content": feed_item.content,
"desc": feed_item.summary,
"official_type": feed_item.category.value,
"created_at": int(feed_item.published.timestamp()),
},
Expand Down
16 changes: 8 additions & 8 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,34 @@ python =

[testenv]
deps =
pytest == 8.2.2
pytest-asyncio == 0.23.7
pytest-cov == 5.0.0
pytest == 8.3.4
pytest-asyncio == 0.24.0
pytest-cov == 6.0.0
pytest-mock == 3.14.0
coverage[toml] == 7.5.4
coverage[toml] == 7.6.9
atoma == 0.0.17
langdetect == 1.0.9
commands = pytest {posargs}

[testenv:type]
deps =
mypy == 1.10.1
mypy == 1.13.0
{[testenv]deps}
commands = mypy --install-types --non-interactive {posargs}

[testenv:clean]
skip_install = true
deps = coverage[toml] == 7.4.0
deps = coverage[toml] == 7.6.9
commands = coverage erase

[testenv:black]
skip_install = true
deps = black == 24.4.2
deps = black == 24.10.0
commands = black src tests {posargs}

[testenv:flake]
skip_install = true
deps = flake8 == 7.1.0
deps = flake8 == 7.1.1
commands = flake8 {posargs}


Expand Down

0 comments on commit 330e35b

Please sign in to comment.