236 lines
7.1 KiB
Python
236 lines
7.1 KiB
Python
|
|
# retoor <retoor@molodetz.nl>
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from devplacepy_services.base.compound import (
|
||
|
|
AttachmentsIn,
|
||
|
|
AwardsBundleIn,
|
||
|
|
BookmarksIn,
|
||
|
|
CacheBumpIn,
|
||
|
|
CommentCountsIn,
|
||
|
|
CommentsIn,
|
||
|
|
FeedPageIn,
|
||
|
|
FollowBundleIn,
|
||
|
|
LeaderboardBundleIn,
|
||
|
|
NotificationPrefsIn,
|
||
|
|
OnlineUsersIn,
|
||
|
|
PollsIn,
|
||
|
|
ReactionsIn,
|
||
|
|
RecentCommentsIn,
|
||
|
|
RelationsIn,
|
||
|
|
SeoMetaIn,
|
||
|
|
SiteSidebarIn,
|
||
|
|
UserMediaIn,
|
||
|
|
UsersByUidsIn,
|
||
|
|
VoteCountsIn,
|
||
|
|
)
|
||
|
|
from devplacepy_services.base.errors import http_error
|
||
|
|
from devplacepy_services.base.http import internal_request
|
||
|
|
|
||
|
|
|
||
|
|
class BrokerClient:
|
||
|
|
def __init__(self, name: str, url: str | None = None) -> None:
|
||
|
|
self.name = name
|
||
|
|
if url is not None:
|
||
|
|
self.url = url.rstrip("/")
|
||
|
|
else:
|
||
|
|
from devplacepy_services.base.config import broker_url
|
||
|
|
|
||
|
|
self.url = broker_url(name).rstrip("/")
|
||
|
|
|
||
|
|
async def post(self, path: str, body: dict[str, Any] | None = None) -> Any:
|
||
|
|
target = f"{self.url}/{path.lstrip('/')}"
|
||
|
|
response = await internal_request("POST", target, json=body or {})
|
||
|
|
if response.status_code >= 400:
|
||
|
|
payload = response.json() if response.content else {}
|
||
|
|
message = payload.get("error", "Broker request failed")
|
||
|
|
code = payload.get("code", "broker_error")
|
||
|
|
raise http_error(response.status_code, message, code)
|
||
|
|
if not response.content:
|
||
|
|
return None
|
||
|
|
return response.json()
|
||
|
|
|
||
|
|
async def get(self, path: str, *, params: dict[str, Any] | None = None) -> Any:
|
||
|
|
target = f"{self.url}/{path.lstrip('/')}"
|
||
|
|
response = await internal_request("GET", target, params=params)
|
||
|
|
if response.status_code >= 400:
|
||
|
|
payload = response.json() if response.content else {}
|
||
|
|
message = payload.get("error", "Broker request failed")
|
||
|
|
code = payload.get("code", "broker_error")
|
||
|
|
raise http_error(response.status_code, message, code)
|
||
|
|
if not response.content:
|
||
|
|
return None
|
||
|
|
return response.json()
|
||
|
|
|
||
|
|
|
||
|
|
main = BrokerClient("main")
|
||
|
|
devii_tasks = BrokerClient("devii_tasks")
|
||
|
|
devii_lessons = BrokerClient("devii_lessons")
|
||
|
|
|
||
|
|
|
||
|
|
async def get_setting(key: str, default: str = "") -> str:
|
||
|
|
payload = await main.get(f"settings/{key}", params={"default": default})
|
||
|
|
return payload.get("value", default) if isinstance(payload, dict) else default
|
||
|
|
|
||
|
|
|
||
|
|
async def get_int_setting(key: str, default: int) -> int:
|
||
|
|
raw = await get_setting(key, str(default))
|
||
|
|
try:
|
||
|
|
return int(raw)
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return default
|
||
|
|
|
||
|
|
|
||
|
|
async def bump_cache_version(name: str) -> None:
|
||
|
|
await main.post("/cache/bump", CacheBumpIn(name=name).model_dump())
|
||
|
|
|
||
|
|
|
||
|
|
async def get_users_by_uids(uids: list[str]) -> dict:
|
||
|
|
return await main.post("/compound/users-by-uids", UsersByUidsIn(uids=uids).model_dump())
|
||
|
|
|
||
|
|
|
||
|
|
async def get_comment_counts_by_post_uids(post_uids: list[str]) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/comment-counts", CommentCountsIn(post_uids=post_uids).model_dump()
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_vote_counts(target_uids: list[str]) -> tuple[dict, dict]:
|
||
|
|
payload = await main.post(
|
||
|
|
"/compound/vote-counts", VoteCountsIn(target_uids=target_uids).model_dump()
|
||
|
|
)
|
||
|
|
return payload.get("ups", {}), payload.get("downs", {})
|
||
|
|
|
||
|
|
|
||
|
|
async def get_reactions_by_targets(
|
||
|
|
target_type: str, target_uids: list[str], user: dict | None = None
|
||
|
|
) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/reactions",
|
||
|
|
ReactionsIn(target_type=target_type, target_uids=target_uids, user=user).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_user_bookmarks(
|
||
|
|
user_uid: str, target_type: str, target_uids: list[str]
|
||
|
|
) -> set[str]:
|
||
|
|
payload = await main.post(
|
||
|
|
"/compound/bookmarks",
|
||
|
|
BookmarksIn(
|
||
|
|
user_uid=user_uid, target_type=target_type, target_uids=target_uids
|
||
|
|
).model_dump(),
|
||
|
|
)
|
||
|
|
return set(payload or [])
|
||
|
|
|
||
|
|
|
||
|
|
async def get_polls_by_post_uids(post_uids: list[str], user: dict | None = None) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/polls", PollsIn(post_uids=post_uids, user=user).model_dump()
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_recent_comments_by_post_uids(
|
||
|
|
post_uids: list[str], limit: int = 3, user: dict | None = None
|
||
|
|
) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/recent-comments",
|
||
|
|
RecentCommentsIn(post_uids=post_uids, limit=limit, user=user).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def load_comments(
|
||
|
|
target_type: str, target_uid: str, user: dict | None = None
|
||
|
|
) -> list:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/comments",
|
||
|
|
CommentsIn(target_type=target_type, target_uid=target_uid, user=user).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_follow_bundle(
|
||
|
|
user_uid: str, target_uids: list[str] | None = None
|
||
|
|
) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/follow-bundle",
|
||
|
|
FollowBundleIn(user_uid=user_uid, target_uids=target_uids).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_user_relations_bundle(viewer_uid: str | None = None) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/relations", RelationsIn(viewer_uid=viewer_uid).model_dump()
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_online_users(cutoff_iso: str, limit: int = 30) -> list:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/online-users",
|
||
|
|
OnlineUsersIn(cutoff_iso=cutoff_iso, limit=limit).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_notification_prefs(user_uid: str) -> list:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/notification-prefs",
|
||
|
|
NotificationPrefsIn(user_uid=user_uid).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_leaderboard_bundle(
|
||
|
|
limit: int = 50, offset: int = 0, viewer_uid: str | None = None
|
||
|
|
) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/leaderboard",
|
||
|
|
LeaderboardBundleIn(limit=limit, offset=offset, viewer_uid=viewer_uid).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_site_sidebar(authors_limit: int = 5) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/site-sidebar", SiteSidebarIn(authors_limit=authors_limit).model_dump()
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_awards_bundle(
|
||
|
|
receiver_uid: str,
|
||
|
|
page: int = 1,
|
||
|
|
per_page: int = 12,
|
||
|
|
profile_user: dict | None = None,
|
||
|
|
) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/awards",
|
||
|
|
AwardsBundleIn(
|
||
|
|
receiver_uid=receiver_uid,
|
||
|
|
page=page,
|
||
|
|
per_page=per_page,
|
||
|
|
profile_user=profile_user,
|
||
|
|
).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_attachments_batch(resource_type: str, resource_uids: list[str]) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/attachments",
|
||
|
|
AttachmentsIn(resource_type=resource_type, resource_uids=resource_uids).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_user_media(
|
||
|
|
user_uid: str, page: int = 1, per_page: int = 24
|
||
|
|
) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/user-media",
|
||
|
|
UserMediaIn(user_uid=user_uid, page=page, per_page=per_page).model_dump(),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def get_seo_metadata_batch(target_type: str, uids: list[str]) -> dict:
|
||
|
|
return await main.post(
|
||
|
|
"/compound/seo-meta", SeoMetaIn(target_type=target_type, uids=uids).model_dump()
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
async def build_feed_page(**kwargs) -> dict:
|
||
|
|
return await main.post("/compound/feed-page", FeedPageIn(**kwargs).model_dump())
|