Coverage for apps/kwai-api/src/kwai_api/v1/news/presenters.py: 92%
38 statements
« prev ^ index » next coverage.py v7.11.0, created at 2024-01-01 00:00 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2024-01-01 00:00 +0000
1"""Module that defines presenters for the portal/news endpoint."""
3from typing import Self
5from kwai_bc_identity.users.user import UserEntity
6from kwai_bc_portal.domain.application import ApplicationEntity
7from kwai_bc_portal.domain.news_item import NewsItemEntity
8from kwai_core.domain.exceptions import NotAllowedException
9from kwai_core.domain.presenter import AsyncPresenter, IterableResult, Presenter
10from kwai_core.json_api import JsonApiPresenter, Meta, Relationship, ResourceMeta
12from kwai_api.converter import MarkdownConverter
13from kwai_api.schemas.resources import ApplicationResourceIdentifier
14from kwai_api.v1.news.schemas import (
15 NewsApplicationAttributes,
16 NewsApplicationDocument,
17 NewsApplicationResource,
18 NewsItemAttributes,
19 NewsItemDocument,
20 NewsItemRelationships,
21 NewsItemResource,
22 NewsItemsDocument,
23 NewsItemText,
24)
27class JsonApiNewsApplicationPresenter(
28 JsonApiPresenter[NewsApplicationDocument], Presenter[ApplicationEntity]
29):
30 """A presenter that transforms a news application into a JSON:API document."""
32 def present(self, news_application: ApplicationEntity) -> Self:
33 self._document = NewsApplicationDocument(
34 data=NewsApplicationResource(
35 id=str(news_application.id),
36 attributes=NewsApplicationAttributes(
37 name=news_application.name, title=news_application.title
38 ),
39 )
40 )
41 return self
44class JsonApiNewsItemPresenter(
45 JsonApiPresenter[NewsItemDocument], Presenter[NewsItemEntity]
46):
47 """A presenter that transform a news item entity into a JSON:API document."""
49 def __init__(self, user: UserEntity | None):
50 super().__init__()
51 self._user = user
53 def present(self, news_item: NewsItemEntity) -> Self:
54 # Only a know user is allowed to see disabled news.
55 if not self._user and not news_item.enabled:
56 raise NotAllowedException(
57 f"Not allowed to view the news item {news_item.id}"
58 )
60 application_document = (
61 JsonApiNewsApplicationPresenter()
62 .present(news_item.application)
63 .get_document()
64 )
65 self._document = NewsItemDocument(
66 data=NewsItemResource(
67 id=str(news_item.id),
68 meta=ResourceMeta(
69 created_at=str(news_item.traceable_time.created_at),
70 updated_at=str(news_item.traceable_time.updated_at),
71 ),
72 attributes=NewsItemAttributes(
73 priority=news_item.promotion.priority,
74 publish_date=str(news_item.period.start_date),
75 end_date=str(news_item.period.end_date),
76 enabled=news_item.enabled,
77 remark=news_item.remark or "",
78 promotion_end_date=str(news_item.promotion.end_date),
79 texts=[
80 NewsItemText(
81 locale=text.locale.value,
82 format=text.format.value,
83 title=text.title,
84 summary=MarkdownConverter().convert(text.summary),
85 content=MarkdownConverter().convert(text.content)
86 if text.content
87 else None,
88 original_summary=text.summary,
89 original_content=text.content,
90 )
91 for text in news_item.texts
92 ],
93 ),
94 relationships=NewsItemRelationships(
95 application=Relationship[ApplicationResourceIdentifier](
96 data=ApplicationResourceIdentifier(
97 id=str(news_item.application.id)
98 )
99 )
100 ),
101 ),
102 included={application_document.data},
103 )
104 return self
107class JsonApiNewsItemsPresenter(
108 JsonApiPresenter[NewsItemsDocument], AsyncPresenter[IterableResult[NewsItemEntity]]
109):
110 """A presenter that transfer an iterable list of news items into a JSON:API document."""
112 def __init__(self, user: UserEntity | None):
113 super().__init__()
114 self._user = user
116 async def present(self, result: IterableResult[NewsItemEntity]) -> Self:
117 self._document = NewsItemsDocument(
118 meta=Meta(count=result.count, offset=result.offset, limit=result.limit),
119 data=[],
120 )
121 async for news_item in result.iterator:
122 try:
123 news_item_document = (
124 JsonApiNewsItemPresenter(self._user)
125 .present(news_item)
126 .get_document()
127 )
128 self._document.data.append(news_item_document.data)
129 self._document.included |= news_item_document.included
130 except NotAllowedException:
131 pass
133 return self