from __future__ import annotations from yuxi.channel.extensions.kakaotalk.types import KakaoButton, KakaoQuickReply class CardBuilder: @staticmethod def simple_text(text: str) -> dict: return {"simpleText": {"text": text[:1000]}} @staticmethod def simple_image(image_url: str, alt_text: str) -> dict: return {"simpleImage": {"imageUrl": image_url, "altText": alt_text}} @staticmethod def basic_card( title: str, description: str = "", thumbnail_url: str | None = None, buttons: list[KakaoButton] | None = None, button_layout: str = "vertical", profile_nickname: str | None = None, profile_image_url: str | None = None, forwardable: bool | None = None, social_like: int = 0, social_comment: int = 0, social_share: int = 0, ) -> dict: card: dict = {"title": title, "description": description} if thumbnail_url: card["thumbnail"] = {"imageUrl": thumbnail_url} if profile_nickname: card["profile"] = {"nickname": profile_nickname} if profile_image_url: card["profile"]["imageUrl"] = profile_image_url if buttons: card["buttons"] = [CardBuilder._build_button(b) for b in buttons] card["buttonLayout"] = button_layout if forwardable is not None: card["forwardable"] = forwardable if social_like or social_comment or social_share: card["social"] = { "like": social_like, "comment": social_comment, "share": social_share, } return {"basicCard": card} @staticmethod def commerce_card( title: str, description: str = "", price: int = 0, currency: str = "won", discount: int = 0, discount_rate: int = 0, discounted_price: int = 0, thumbnail_urls: list[str] | None = None, profile_nickname: str | None = None, profile_image_url: str | None = None, buttons: list[KakaoButton] | None = None, button_layout: str = "vertical", ) -> dict: card: dict = { "title": title, "description": description, "price": price, "currency": currency, } if discount: card["discount"] = discount if discount_rate: card["discountRate"] = discount_rate if discounted_price: card["discountedPrice"] = discounted_price if thumbnail_urls: card["thumbnails"] = [ {"imageUrl": url, "fixedRatio": True, "width": 800, "height": 800} for url in thumbnail_urls ] if profile_nickname: card["profile"] = {"nickname": profile_nickname} if profile_image_url: card["profile"]["imageUrl"] = profile_image_url if buttons: card["buttons"] = [CardBuilder._build_button(b) for b in buttons] card["buttonLayout"] = button_layout return {"commerceCard": card} @staticmethod def list_card( header_title: str, items: list[dict], buttons: list[KakaoButton] | None = None, button_layout: str = "vertical", ) -> dict: card: dict = {"header": {"title": header_title}, "items": items} if buttons: card["buttons"] = [CardBuilder._build_button(b) for b in buttons] card["buttonLayout"] = button_layout return {"listCard": card} @staticmethod def carousel(card_type: str, items: list[dict]) -> dict: return {"carousel": {"type": card_type, "items": items}} @staticmethod def commerce_carousel(commerce_items: list[dict]) -> dict: return {"carousel": {"type": "commerceCard", "items": commerce_items}} @staticmethod def text_card( title: str, description: str = "", buttons: list[KakaoButton] | None = None, button_layout: str = "vertical", ) -> dict: card: dict = {"title": title[:50], "description": description[:400]} if buttons: card["buttons"] = [CardBuilder._build_button(b) for b in buttons] card["buttonLayout"] = button_layout return {"textCard": card} @staticmethod def item_card( title: str = "", description: str = "", thumbnail_url: str | None = None, item_list: list[dict] | None = None, buttons: list[KakaoButton] | None = None, button_layout: str = "vertical", profile_nickname: str | None = None, profile_image_url: str | None = None, head_title: str = "", image_title: str = "", image_title_image_url: str | None = None, ) -> dict: card: dict = {} if title: card["title"] = title if description: card["description"] = description if thumbnail_url: card["thumbnail"] = {"imageUrl": thumbnail_url} if item_list: card["itemList"] = item_list if head_title: card["head"] = {"title": head_title} if image_title: img_title: dict = {"title": image_title} if image_title_image_url: img_title["imageUrl"] = image_title_image_url card["imageTitle"] = img_title if profile_nickname: card["profile"] = {"nickname": profile_nickname} if profile_image_url: card["profile"]["imageUrl"] = profile_image_url if buttons: card["buttons"] = [CardBuilder._build_button(b) for b in buttons] card["buttonLayout"] = button_layout return {"itemCard": card} @staticmethod def build_list_card_item( title: str, description: str = "", image_url: str | None = None, link_url: str | None = None, ) -> dict: item: dict = {"title": title} if description: item["description"] = description if image_url: item["imageUrl"] = image_url if link_url: item["link"] = {"web": link_url} return item @staticmethod def build_item_card_item( title: str, description: str = "", image_url: str | None = None, link_url: str | None = None, ) -> dict: item: dict = {"title": title} if description: item["description"] = description if image_url: item["imageUrl"] = image_url if link_url: item["link"] = {"web": link_url} return item @staticmethod def quick_reply(reply: KakaoQuickReply) -> dict: qr: dict = {"label": reply.label, "action": reply.action} if reply.message_text: qr["messageText"] = reply.message_text if reply.block_id: qr["blockId"] = reply.block_id if reply.web_link_url: qr["webLinkUrl"] = reply.web_link_url if reply.extra: qr["extra"] = reply.extra return qr @staticmethod def quick_replies(replies: list[dict]) -> list[dict]: return replies @staticmethod def build_skill_response( outputs: list[dict], quick_replies: list[dict] | None = None, context_values: list[dict] | None = None, data: dict | None = None, ) -> dict: template: dict = {"outputs": outputs} if quick_replies: template["quickReplies"] = quick_replies skill_response: dict = {"version": "2.0", "template": template} if context_values: skill_response["context"] = {"values": context_values} if data: skill_response["data"] = data return skill_response @staticmethod def build_context_value( name: str, life_span: int, ttl: int = 0, params: dict | None = None, ) -> dict: cv: dict = {"name": name, "lifeSpan": life_span} if ttl: cv["ttl"] = ttl if params: cv["params"] = params return cv @staticmethod def _build_button(button: KakaoButton) -> dict: btn: dict = {"label": button.label, "action": button.action} if button.message_text: btn["messageText"] = button.message_text if button.web_link_url: btn["webLinkUrl"] = button.web_link_url if button.phone_number: btn["phoneNumber"] = button.phone_number if button.block_id: btn["blockId"] = button.block_id if button.bot_command_id: btn["botCommand"] = {"commandId": button.bot_command_id} if button.operator_block_id: btn["operatorBlock"] = {"blockId": button.operator_block_id} if button.extra: btn["extra"] = button.extra return btn