|
4 | 4 | from abc import ABC, abstractmethod |
5 | 5 | from datetime import date, datetime, time |
6 | 6 | from typing import Any, Final, Literal, Self, TypeAlias, get_args |
| 7 | +from urllib import parse |
7 | 8 | from zoneinfo import ZoneInfo |
8 | 9 |
|
9 | 10 | from blockkit.utils import is_md |
@@ -741,6 +742,28 @@ def external_id(self, external_id: str | None) -> Self: |
741 | 742 | ) |
742 | 743 |
|
743 | 744 |
|
| 745 | +class BuilderUrlMixin: |
| 746 | + def builder_url(self) -> str: |
| 747 | + """ |
| 748 | + Returns a URL to preview this message in Slack's Block Kit Builder. |
| 749 | + """ |
| 750 | + |
| 751 | + surface = self.build() |
| 752 | + filter_fields = { |
| 753 | + Message: ("blocks",), |
| 754 | + Modal: ("type", "title", "submit", "close", "blocks"), |
| 755 | + Home: ("type", "blocks"), |
| 756 | + }.get(type(self), None) |
| 757 | + |
| 758 | + if filter_fields: |
| 759 | + surface = {k: v for k, v in surface.items() if k in filter_fields} |
| 760 | + |
| 761 | + encoded_json = parse.quote( |
| 762 | + json.dumps(surface, ensure_ascii=False, separators=(",", ":")), safe="" |
| 763 | + ) |
| 764 | + return f"https://app.slack.com/block-kit-builder#{encoded_json}" |
| 765 | + |
| 766 | + |
744 | 767 | """ |
745 | 768 | Composition objects |
746 | 769 | """ |
@@ -3192,7 +3215,7 @@ def author_name(self, author_name: str | None) -> Self: |
3192 | 3215 | ) |
3193 | 3216 |
|
3194 | 3217 |
|
3195 | | -class Message(Component): |
| 3218 | +class Message(Component, BuilderUrlMixin): |
3196 | 3219 | """ |
3197 | 3220 | Message surface |
3198 | 3221 |
|
@@ -3242,7 +3265,12 @@ def mrkdwn(self, mrkdwn: bool | None = True) -> Self: |
3242 | 3265 |
|
3243 | 3266 |
|
3244 | 3267 | class Modal( |
3245 | | - Component, BlocksMixin, PrivateMetadataMixin, CallbackIdMixin, ExternalIdMixin |
| 3268 | + Component, |
| 3269 | + BlocksMixin, |
| 3270 | + PrivateMetadataMixin, |
| 3271 | + CallbackIdMixin, |
| 3272 | + ExternalIdMixin, |
| 3273 | + BuilderUrlMixin, |
3246 | 3274 | ): |
3247 | 3275 | """ |
3248 | 3276 | Modal surface |
@@ -3320,7 +3348,12 @@ def submit_disabled(self, submit_disabled: bool | None = True) -> Self: |
3320 | 3348 |
|
3321 | 3349 |
|
3322 | 3350 | class Home( |
3323 | | - Component, BlocksMixin, PrivateMetadataMixin, CallbackIdMixin, ExternalIdMixin |
| 3351 | + Component, |
| 3352 | + BlocksMixin, |
| 3353 | + PrivateMetadataMixin, |
| 3354 | + CallbackIdMixin, |
| 3355 | + ExternalIdMixin, |
| 3356 | + BuilderUrlMixin, |
3324 | 3357 | ): |
3325 | 3358 | """ |
3326 | 3359 | App Home surface |
|
0 commit comments