django-slack-tools 0.2.2__py3-none-any.whl → 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. django_slack_tools/__init__.py +0 -1
  2. django_slack_tools/app_settings.py +54 -90
  3. django_slack_tools/locale/ko_KR/LC_MESSAGES/django.po +150 -186
  4. django_slack_tools/py.typed +0 -0
  5. django_slack_tools/slack_messages/admin/message.py +1 -52
  6. django_slack_tools/slack_messages/admin/message_recipient.py +2 -2
  7. django_slack_tools/slack_messages/admin/messaging_policy.py +5 -5
  8. django_slack_tools/slack_messages/backends/__init__.py +3 -3
  9. django_slack_tools/slack_messages/backends/base.py +39 -203
  10. django_slack_tools/slack_messages/backends/dummy.py +0 -12
  11. django_slack_tools/slack_messages/backends/{logging.py → logging_.py} +0 -6
  12. django_slack_tools/slack_messages/backends/slack.py +21 -75
  13. django_slack_tools/slack_messages/message_templates/__init__.py +5 -0
  14. django_slack_tools/slack_messages/message_templates/base.py +17 -0
  15. django_slack_tools/{utils/template → slack_messages/message_templates}/django.py +30 -25
  16. django_slack_tools/slack_messages/message_templates/python.py +38 -0
  17. django_slack_tools/slack_messages/messenger.py +158 -0
  18. django_slack_tools/slack_messages/middlewares/__init__.py +4 -0
  19. django_slack_tools/slack_messages/middlewares/base.py +34 -0
  20. django_slack_tools/slack_messages/middlewares/django.py +218 -0
  21. django_slack_tools/slack_messages/migrations/0001_initial.py +4 -4
  22. django_slack_tools/slack_messages/migrations/0005_alter_slackmessagingpolicy_template_type.py +46 -0
  23. django_slack_tools/slack_messages/migrations/0006_alter_slackmessage_id.py +26 -0
  24. django_slack_tools/slack_messages/models/mention.py +1 -1
  25. django_slack_tools/slack_messages/models/message.py +5 -2
  26. django_slack_tools/slack_messages/models/message_recipient.py +1 -1
  27. django_slack_tools/slack_messages/models/messaging_policy.py +4 -4
  28. django_slack_tools/slack_messages/request.py +91 -0
  29. django_slack_tools/slack_messages/response.py +21 -0
  30. django_slack_tools/slack_messages/shortcuts.py +78 -0
  31. django_slack_tools/slack_messages/tasks.py +8 -57
  32. django_slack_tools/slack_messages/template_loaders/__init__.py +11 -0
  33. django_slack_tools/slack_messages/template_loaders/base.py +16 -0
  34. django_slack_tools/slack_messages/template_loaders/django.py +74 -0
  35. django_slack_tools/slack_messages/template_loaders/errors.py +9 -0
  36. django_slack_tools/{utils/slack/django.py → slack_messages/validators.py} +1 -1
  37. django_slack_tools/utils/django/__init__.py +0 -0
  38. django_slack_tools/utils/import_helper.py +37 -0
  39. django_slack_tools/utils/repr.py +10 -0
  40. django_slack_tools/utils/slack/__init__.py +1 -9
  41. {django_slack_tools-0.2.2.dist-info → django_slack_tools-0.3.1.dist-info}/METADATA +12 -60
  42. django_slack_tools-0.3.1.dist-info/RECORD +58 -0
  43. {django_slack_tools-0.2.2.dist-info → django_slack_tools-0.3.1.dist-info}/WHEEL +1 -1
  44. django_slack_tools/slack_messages/message.py +0 -110
  45. django_slack_tools/utils/slack/message.py +0 -93
  46. django_slack_tools/utils/template/__init__.py +0 -5
  47. django_slack_tools/utils/template/base.py +0 -17
  48. django_slack_tools/utils/template/dict.py +0 -52
  49. django_slack_tools-0.2.2.dist-info/RECORD +0 -43
  50. /django_slack_tools/utils/{model_mixins.py → django/model_mixins.py} +0 -0
  51. /django_slack_tools/utils/{widgets.py → django/widgets.py} +0 -0
  52. {django_slack_tools-0.2.2.dist-info → django_slack_tools-0.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,91 @@
1
+ # noqa: D100
2
+ # flake8: noqa: UP006, UP007, UP035
3
+ # #? Subscription syntax available since Python 3.10
4
+ from __future__ import annotations
5
+
6
+ import uuid
7
+ from typing import Any, Dict, List, Optional
8
+
9
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
10
+
11
+
12
+ class MessageRequest(BaseModel):
13
+ """Message request object."""
14
+
15
+ model_config = ConfigDict(extra="forbid")
16
+
17
+ id_: str = Field(default_factory=lambda: str(uuid.uuid4()))
18
+ channel: Any
19
+
20
+ # Template key is optional to allow lazy initialization of the template key
21
+ template_key: Optional[str]
22
+
23
+ context: Dict[str, Any]
24
+ header: MessageHeader
25
+
26
+ # Also, the body is optional because it is rendered from the template
27
+ body: Optional[MessageBody] = None
28
+
29
+
30
+ class MessageHeader(BaseModel): # noqa: D101
31
+ model_config = ConfigDict(extra="forbid")
32
+
33
+ mrkdwn: Optional[str] = None
34
+ parse: Optional[str] = None
35
+ reply_broadcast: Optional[bool] = None
36
+ thread_ts: Optional[str] = None
37
+ unfurl_links: Optional[bool] = None
38
+ unfurl_media: Optional[bool] = None
39
+
40
+ @classmethod
41
+ def from_any(cls, obj: MessageHeader | dict[str, Any] | None = None) -> MessageHeader:
42
+ """Create instance from compatible types."""
43
+ if isinstance(obj, cls):
44
+ return obj
45
+
46
+ if isinstance(obj, dict):
47
+ return cls.model_validate(obj)
48
+
49
+ if obj is None:
50
+ return cls()
51
+
52
+ msg = f"Unsupported type {type(obj)}"
53
+ raise TypeError(msg)
54
+
55
+
56
+ class MessageBody(BaseModel): # noqa: D101
57
+ model_config = ConfigDict(extra="forbid")
58
+
59
+ attachments: Optional[List[dict]] = None
60
+
61
+ # See more about blocks at https://api.slack.com/reference/block-kit/blocks
62
+ blocks: Optional[list[dict]] = None
63
+
64
+ text: Optional[str] = None
65
+ icon_emoji: Optional[str] = None
66
+ icon_url: Optional[str] = None
67
+ metadata: Optional[dict] = None
68
+ username: Optional[str] = None
69
+
70
+ @model_validator(mode="after")
71
+ def _check_at_least_one_field_is_set(self) -> MessageBody:
72
+ if not any((self.attachments, self.blocks, self.text)):
73
+ msg = "At least one of `attachments`, `blocks` and `text` must set"
74
+ raise ValueError(msg)
75
+
76
+ return self
77
+
78
+ @classmethod
79
+ def from_any(cls, obj: str | MessageBody | dict[str, Any]) -> MessageBody:
80
+ """Create instance from compatible types."""
81
+ if isinstance(obj, cls):
82
+ return obj
83
+
84
+ if isinstance(obj, dict):
85
+ return cls.model_validate(obj)
86
+
87
+ if isinstance(obj, str):
88
+ return cls(text=obj)
89
+
90
+ msg = f"Unsupported type {type(obj)}"
91
+ raise TypeError(msg)
@@ -0,0 +1,21 @@
1
+ # noqa: D100
2
+ # flake8: noqa: UP006, UP007, UP035
3
+ # ? Subscription syntax available since Python 3.10
4
+ from __future__ import annotations
5
+
6
+ from typing import Any, Optional
7
+
8
+ from pydantic import BaseModel
9
+
10
+ from django_slack_tools.slack_messages.request import MessageRequest # noqa: TC001
11
+
12
+
13
+ class MessageResponse(BaseModel):
14
+ """Response from a messaging backend."""
15
+
16
+ request: Optional[MessageRequest] = None
17
+ ok: bool
18
+ error: Optional[Any] = None
19
+ data: Any
20
+ ts: Optional[str] = None
21
+ parent_ts: Optional[str] = None
@@ -0,0 +1,78 @@
1
+ """Handy APIs for sending Slack messages."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ from typing import TYPE_CHECKING, Any, overload
7
+
8
+ from django_slack_tools.app_settings import get_messenger
9
+ from django_slack_tools.slack_messages.request import MessageBody, MessageHeader, MessageRequest
10
+
11
+ if TYPE_CHECKING:
12
+ from django_slack_tools.slack_messages.response import MessageResponse
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ @overload
18
+ def slack_message(
19
+ to: str,
20
+ *,
21
+ messenger_name: str | None = None,
22
+ header: MessageHeader | dict[str, Any] | None = None,
23
+ message: str,
24
+ ) -> MessageResponse | None: ... # pragma: no cover
25
+
26
+
27
+ @overload
28
+ def slack_message(
29
+ to: str,
30
+ *,
31
+ messenger_name: str | None = None,
32
+ header: MessageHeader | dict[str, Any] | None = None,
33
+ template: str | None = None,
34
+ context: dict[str, Any] | None = None,
35
+ ) -> MessageResponse | None: ... # pragma: no cover
36
+
37
+
38
+ def slack_message( # noqa: PLR0913
39
+ to: str,
40
+ *,
41
+ messenger_name: str | None = None,
42
+ header: MessageHeader | dict[str, Any] | None = None,
43
+ template: str | None = None,
44
+ context: dict[str, Any] | None = None,
45
+ message: str | None = None,
46
+ ) -> MessageResponse | None:
47
+ """Shortcut for sending a Slack message.
48
+
49
+ Args:
50
+ to: Recipient.
51
+ messenger_name: Messenger name. If not set, default messenger is used.
52
+ header: Slack message control header.
53
+ template: Message template key. Cannot be used with `message`.
54
+ context: Context for rendering the template. Only used with `template`.
55
+ message: Simple message text. Cannot be used with `template`.
56
+
57
+ Returns:
58
+ Sent message instance or `None`.
59
+ """
60
+ if (template and message) or (not template and not message):
61
+ msg = "Either `template` or `message` must be set, but not both."
62
+ raise ValueError(msg)
63
+
64
+ messenger = get_messenger(messenger_name)
65
+ header = MessageHeader.from_any(header)
66
+
67
+ if message:
68
+ request = MessageRequest(
69
+ channel=to,
70
+ header=header,
71
+ body=MessageBody(text=message),
72
+ template_key=None,
73
+ context={},
74
+ )
75
+ return messenger.send_request(request)
76
+
77
+ context = context or {}
78
+ return messenger.send(to, header=header, template=template, context=context)
@@ -9,7 +9,7 @@ from celery import shared_task
9
9
  from celery.utils.log import get_task_logger
10
10
  from django.utils import timezone
11
11
 
12
- from django_slack_tools.slack_messages import message
12
+ from django_slack_tools.slack_messages import shortcuts
13
13
  from django_slack_tools.slack_messages.models import SlackMessage
14
14
 
15
15
  if TYPE_CHECKING:
@@ -19,67 +19,18 @@ logger = get_task_logger(__name__)
19
19
 
20
20
 
21
21
  @shared_task
22
- def slack_message(
23
- body: str | dict[str, Any],
24
- *,
25
- channel: str,
26
- header: dict[str, Any] | None = None,
27
- raise_exception: bool = False,
28
- get_permalink: bool = False,
29
- ) -> int | None:
30
- """Celery task wrapper for `message.slack_message`.
31
-
32
- Args:
33
- body: Message content, simple message or full request body.
34
- channel: Channel to send message.
35
- header: Slack message control header.
36
- raise_exception: Whether to re-raise caught exception while sending messages.
37
- get_permalink: Try to get the message permalink via extraneous Slack API calls.
38
-
39
- Returns:
40
- ID of sent message.
41
- """
42
- sent_msg = message.slack_message(
43
- body,
44
- channel=channel,
45
- header=header,
46
- raise_exception=raise_exception,
47
- get_permalink=get_permalink,
48
- )
49
- return sent_msg.id
50
-
51
-
52
- @shared_task
53
- def slack_message_via_policy( # noqa: PLR0913
54
- policy: str,
55
- *,
56
- header: dict[str, Any] | None = None,
57
- raise_exception: bool = False,
58
- lazy: bool = False,
59
- get_permalink: bool = False,
60
- context: dict[str, Any] | None = None,
61
- ) -> int:
62
- """Celery task wrapper for `message.slack_message_via_policy`.
22
+ def slack_message(*args: Any, **kwargs: Any) -> str | None:
23
+ """Celery task wrapper for `.shortcuts.slack_message`.
63
24
 
64
25
  Args:
65
- policy: Messaging policy code.
66
- header: Slack message control header.
67
- raise_exception: Whether to re-raise caught exception while sending messages.
68
- lazy: Decide whether try to create policy with disabled, if not exists.
69
- get_permalink: Try to get the message permalink via extraneous Slack API calls.
70
- context: Context variables for message rendering.
26
+ args: Positional arguments.
27
+ kwargs: Keyword arguments.
71
28
 
72
29
  Returns:
73
- Number of sent messages.
30
+ ID of sent message if any, `None` otherwise.
74
31
  """
75
- return message.slack_message_via_policy(
76
- policy,
77
- header=header,
78
- raise_exception=raise_exception,
79
- lazy=lazy,
80
- get_permalink=get_permalink,
81
- context=context,
82
- )
32
+ response = shortcuts.slack_message(*args, **kwargs)
33
+ return response.ts if response else None
83
34
 
84
35
 
85
36
  @shared_task
@@ -0,0 +1,11 @@
1
+ from .base import BaseTemplateLoader
2
+ from .django import DjangoPolicyTemplateLoader, DjangoTemplateLoader
3
+ from .errors import TemplateLoadError, TemplateNotFoundError
4
+
5
+ __all__ = (
6
+ "BaseTemplateLoader",
7
+ "DjangoPolicyTemplateLoader",
8
+ "DjangoTemplateLoader",
9
+ "TemplateLoadError",
10
+ "TemplateNotFoundError",
11
+ )
@@ -0,0 +1,16 @@
1
+ # noqa: D100
2
+ from __future__ import annotations
3
+
4
+ from abc import ABC, abstractmethod
5
+ from typing import TYPE_CHECKING
6
+
7
+ if TYPE_CHECKING:
8
+ from django_slack_tools.slack_messages.message_templates import BaseTemplate
9
+
10
+
11
+ class BaseTemplateLoader(ABC):
12
+ """Base class for template loaders."""
13
+
14
+ @abstractmethod
15
+ def load(self, key: str) -> BaseTemplate | None:
16
+ """Load a template by key."""
@@ -0,0 +1,74 @@
1
+ # noqa: D100
2
+ from __future__ import annotations
3
+
4
+ import logging
5
+ from typing import TYPE_CHECKING
6
+
7
+ from django.template import TemplateDoesNotExist, engines
8
+
9
+ from django_slack_tools.slack_messages.message_templates import DjangoTemplate, PythonTemplate
10
+ from django_slack_tools.slack_messages.models import SlackMessagingPolicy
11
+
12
+ from .base import BaseTemplateLoader
13
+
14
+ if TYPE_CHECKING:
15
+ from django.template.backends.base import BaseEngine
16
+
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class DjangoTemplateLoader(BaseTemplateLoader):
22
+ """Django filesystem-backed template loader."""
23
+
24
+ def __init__(self, *, engine: BaseEngine | None = None) -> None:
25
+ """Initialize template loader.
26
+
27
+ Args:
28
+ engine: Template engine to use. Defaults to Django engine.
29
+ """
30
+ self.engine = engines["django"] if engine is None else engine
31
+
32
+ def load(self, key: str) -> DjangoTemplate | None: # noqa: D102
33
+ try:
34
+ return DjangoTemplate(file=key, engine=self.engine)
35
+ except TemplateDoesNotExist:
36
+ logger.debug("Template not found: %s", key)
37
+ return None
38
+
39
+
40
+ class DjangoPolicyTemplateLoader(BaseTemplateLoader):
41
+ """Django database-backed template loader."""
42
+
43
+ def load(self, key: str) -> PythonTemplate | DjangoTemplate | None: # noqa: D102
44
+ return self._get_template_from_policy(policy_or_code=key)
45
+
46
+ def _get_template_from_policy(
47
+ self,
48
+ policy_or_code: SlackMessagingPolicy | str,
49
+ ) -> PythonTemplate | DjangoTemplate | None:
50
+ """Get template instance."""
51
+ if isinstance(policy_or_code, str):
52
+ try:
53
+ policy = SlackMessagingPolicy.objects.get(code=policy_or_code)
54
+ except SlackMessagingPolicy.DoesNotExist:
55
+ logger.warning("Policy not found: %s", policy_or_code)
56
+ return None
57
+ else:
58
+ policy = policy_or_code
59
+
60
+ if policy.template_type == SlackMessagingPolicy.TemplateType.PYTHON:
61
+ return PythonTemplate(policy.template)
62
+
63
+ if policy.template_type == SlackMessagingPolicy.TemplateType.DJANGO:
64
+ try:
65
+ return DjangoTemplate(file=policy.template)
66
+ except TemplateDoesNotExist:
67
+ logger.debug("Template not found: %s", policy.template)
68
+ return None
69
+
70
+ if policy.template_type == SlackMessagingPolicy.TemplateType.DJANGO_INLINE:
71
+ return DjangoTemplate(inline=policy.template)
72
+
73
+ msg = f"Unsupported template type: {policy.template_type!r}"
74
+ raise ValueError(msg)
@@ -0,0 +1,9 @@
1
+ # noqa: D100
2
+
3
+
4
+ class TemplateLoadError(Exception):
5
+ """Base class for template loader errors."""
6
+
7
+
8
+ class TemplateNotFoundError(TemplateLoadError):
9
+ """Template not found error."""
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from django.core.exceptions import ValidationError
6
6
 
7
- from .message import MessageBody, MessageHeader
7
+ from django_slack_tools.slack_messages.request import MessageBody, MessageHeader
8
8
 
9
9
 
10
10
  def header_validator(d: dict) -> None:
File without changes
@@ -0,0 +1,37 @@
1
+ """Application settings."""
2
+ # flake8: noqa: UP007
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Any, TypedDict, Union
7
+
8
+ from django.utils.module_loading import import_string
9
+ from typing_extensions import NotRequired
10
+
11
+ LazyInitSpec = TypedDict(
12
+ "LazyInitSpec",
13
+ {
14
+ "class": str,
15
+ "args": NotRequired[tuple],
16
+ "kwargs": NotRequired[dict[str, Any]],
17
+ },
18
+ )
19
+ LazyInitSupported = Union[LazyInitSpec, str]
20
+
21
+
22
+ def lazy_init(spec: LazyInitSupported) -> Any:
23
+ """Initialize an object from a lazy init spec.
24
+
25
+ If string is passed, it is treated as a class import path.
26
+ Otherwise, it is expected to be a dictionary with keys:
27
+
28
+ - `class`: class import path,
29
+ - `args`: positional arguments,
30
+ - `kwargs`: keyword arguments.
31
+ """
32
+ if isinstance(spec, str):
33
+ spec = LazyInitSpec({"class": spec})
34
+
35
+ class_ = import_string(spec["class"])
36
+ args, kwargs = spec.get("args", ()), spec.get("kwargs", {})
37
+ return class_(*args, **kwargs)
@@ -0,0 +1,10 @@
1
+ # noqa: D100
2
+ from __future__ import annotations
3
+
4
+ from typing import Any
5
+
6
+
7
+ def make_repr(obj: Any) -> str:
8
+ """Make a repr string for an object."""
9
+ args = ", ".join(f"{k}={v!r}" for k, v in obj.__dict__.items())
10
+ return f"{obj.__class__.__name__}({args})"
@@ -1,11 +1,3 @@
1
- from .django import body_validator, header_validator
2
- from .message import MessageBody, MessageHeader
3
1
  from .misc import get_block_kit_builder_url
4
2
 
5
- __all__ = (
6
- "body_validator",
7
- "header_validator",
8
- "MessageBody",
9
- "MessageHeader",
10
- "get_block_kit_builder_url",
11
- )
3
+ __all__ = ("get_block_kit_builder_url",)
@@ -1,16 +1,19 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: django-slack-tools
3
- Version: 0.2.2
3
+ Version: 0.3.1
4
4
  Summary: Little helpers working with Slack bot 🤖 in Django.
5
5
  Author-email: Yuchan Lee <lasuillard@gmail.com>
6
- Requires-Python: <4.0,>=3.8
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: <4.0,>=3.9
7
9
  Requires-Dist: django<5.2,>=4.2
10
+ Requires-Dist: pydantic<3,>=2
8
11
  Requires-Dist: slack-bolt<2,>=1
9
12
  Requires-Dist: xmltodict<1,>=0.14.1
10
13
  Provides-Extra: celery
11
14
  Requires-Dist: celery<6,>=5; extra == 'celery'
12
15
  Provides-Extra: dev
13
- Requires-Dist: django-debug-toolbar~=4.4; extra == 'dev'
16
+ Requires-Dist: django-debug-toolbar<6.0,>=4.4; extra == 'dev'
14
17
  Requires-Dist: django-extensions~=3.2; extra == 'dev'
15
18
  Requires-Dist: django-stubs[compatible-mypy]~=5.1; extra == 'dev'
16
19
  Requires-Dist: ipykernel~=6.27; extra == 'dev'
@@ -23,8 +26,9 @@ Provides-Extra: test
23
26
  Requires-Dist: coverage~=7.3; extra == 'test'
24
27
  Requires-Dist: django-coverage-plugin~=3.1; extra == 'test'
25
28
  Requires-Dist: factory-boy~=3.3; extra == 'test'
26
- Requires-Dist: faker~=30.3; extra == 'test'
27
- Requires-Dist: pytest-cov~=5.0; extra == 'test'
29
+ Requires-Dist: faker<37.0,>=30.3; extra == 'test'
30
+ Requires-Dist: nox<2025.3.0,>=2024.10.9; extra == 'test'
31
+ Requires-Dist: pytest-cov<7,>=5; extra == 'test'
28
32
  Requires-Dist: pytest-django~=4.9; extra == 'test'
29
33
  Requires-Dist: pytest-sugar~=1.0; extra == 'test'
30
34
  Requires-Dist: pytest-xdist~=3.6; extra == 'test'
@@ -66,61 +70,9 @@ And more in future roadmap...
66
70
 
67
71
  Currently it is focused on messaging features. In future, hoping to bring more helpful features across Slack Bot ecosystem, such as event subscriptions, modals, bot interactions, etc.
68
72
 
69
- ## 🚀 Installation
73
+ ## 🗞️ Documentation
70
74
 
71
- **django-slack-tools** supports Python 3.8+ and Django 4.2+. Supports for each deps will be dropped as soon as the ends of security updates.
72
-
73
- > [!WARNING]
74
- > 0.x versions are for development. Breaking changes can be made at any time. If gonna use this package, recommend to pin down the version.
75
-
76
- Install the package:
77
-
78
- ```bash
79
- $ pip install django-slack-tools
80
- ```
81
-
82
- Add the app to the your Django settings:
83
-
84
- ```python
85
- INSTALLED_APPS = [
86
- ...
87
- "django.contrib.messages", # Used in admin
88
- "django_slack_tools.slack_messages",
89
- ...
90
- ]
91
- ```
92
-
93
- Add configuration for application:
94
-
95
- ```python
96
- DJANGO_SLACK_TOOLS = {
97
- # Module path to Slack Bolt application or callable returns the app
98
- "SLACK_APP": "path.to.your.slack.app",
99
-
100
- # Messaging backend configuration
101
- "BACKEND": {
102
- "NAME": "django_slack_tools.slack_messages.backends.SlackBackend",
103
- "OPTIONS": {
104
- # TODO(#44): Reasonable defaults to reduce some duplicates
105
- "slack_app": "path.to.your.slack.app",
106
- }
107
- }
108
- }
109
- ```
110
-
111
- Then, run the database migration and send messages:
112
-
113
- ```python
114
- from django_slack_tools.slack_messages.message import slack_message
115
-
116
- message = slack_message(
117
- "I like threading",
118
- channel="id-of-channel",
119
- header={"reply_broadcast": True},
120
- )
121
- ```
122
-
123
- Please check the [documentation](https://lasuillard.github.io/django-slack-tools/) for more about details.
75
+ Please check the [documentation](https://lasuillard.github.io/django-slack-tools/) for more details.
124
76
 
125
77
  ## 💖 Contributing
126
78
 
@@ -0,0 +1,58 @@
1
+ django_slack_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ django_slack_tools/app_settings.py,sha256=4tM-5vN7XosoSinGfm9wwdm1anN1AAAXlhLYAVUdU48,2858
3
+ django_slack_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ django_slack_tools/views.py,sha256=XuQh0g9A2O51DVkMUhm8x8cswZytZcECNIsDuLsM0UI,1168
5
+ django_slack_tools/locale/ko_KR/LC_MESSAGES/django.po,sha256=o-05SqnUYK7mS5PWO1mFhWEdbPRCm00sue81itdhvco,13813
6
+ django_slack_tools/slack_messages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ django_slack_tools/slack_messages/apps.py,sha256=nLVxuLE-1VIqkcVYEdtlg6ffD3blonGCMKaTd_F5jis,610
8
+ django_slack_tools/slack_messages/messenger.py,sha256=-H7HjfPl8xzQqaW0bqbr8pRhdrLr981eXNPMbILyShQ,6284
9
+ django_slack_tools/slack_messages/request.py,sha256=nDp9oV-rbAKI3nvGNvWc2DWhPE3R3uVKZVwPLwQaM4Q,2643
10
+ django_slack_tools/slack_messages/response.py,sha256=lRW4u07RG_pYghFkmXqiAzHCHic20DvY3nPqOQ1Seas,538
11
+ django_slack_tools/slack_messages/shortcuts.py,sha256=LB-v0GkgByYR0MwH2DqlFPQ_nNCBMMJxa_10HKkdBb4,2337
12
+ django_slack_tools/slack_messages/tasks.py,sha256=I99FYyYP1IpgWUgcIcWFiO47NQYDfV5LYm8NxUUTLec,1823
13
+ django_slack_tools/slack_messages/validators.py,sha256=UpH53b78AgMfk8FKB3eX0tbtrCnLuhF4SI_PS3jfn9Q,776
14
+ django_slack_tools/slack_messages/admin/__init__.py,sha256=FEBZlgze8Nf5wn8ixm9FcsL3na2WYykmm2U-iJXh_mQ,305
15
+ django_slack_tools/slack_messages/admin/mention.py,sha256=Z3Cx-6WKECsbXnyby1qCEMllvxJEIn_TdwexsjEaiIo,4399
16
+ django_slack_tools/slack_messages/admin/message.py,sha256=lYEc67RVRCyak-DMDnOdfh1ZJPrwVSSl7zwiIzqVz2Q,2248
17
+ django_slack_tools/slack_messages/admin/message_recipient.py,sha256=GxzXDG0oY5wp8TTm16LfHsJdvtcbLJm1mPAMD_6UKo8,4039
18
+ django_slack_tools/slack_messages/admin/messaging_policy.py,sha256=DQRBeDPVqjC2f-Tq7g4c18ZuOW1-ViNWuPCkyfFAQPs,4621
19
+ django_slack_tools/slack_messages/backends/__init__.py,sha256=K7xJDVatvksJf7UoPcK3-UO-h5XzE-HJ-nYTihIW6ZM,277
20
+ django_slack_tools/slack_messages/backends/base.py,sha256=8GgmOGSZYoMwQanhintxMCkWgYsyZhpN0aK1J8j1hVo,1877
21
+ django_slack_tools/slack_messages/backends/dummy.py,sha256=Cl6ktqpe4Yoj_rhvVxEmmRc8AmCiDuU9Eprw2Moi_j0,681
22
+ django_slack_tools/slack_messages/backends/logging_.py,sha256=PEIHs34-l-CP8sy5Zp3NHAhUe3nEuYpsxMr4TcjheoM,609
23
+ django_slack_tools/slack_messages/backends/slack.py,sha256=s17w2F2K5UA15qKlyoHObQi_rQZmdX2sWFFkmjNDq6o,2907
24
+ django_slack_tools/slack_messages/message_templates/__init__.py,sha256=KXtUOejEBi9hR9Gn9MwXHIclTmgGsMEHx4vibsbc1uM,165
25
+ django_slack_tools/slack_messages/message_templates/base.py,sha256=p2-JM4QgDTyGlEd6gpJqjTU5lpnPFEJwbVkzJwiELpo,373
26
+ django_slack_tools/slack_messages/message_templates/django.py,sha256=1_MU5ExyRv7t-CgkrGpJ39OQF7Wp9IkVdnBX-ETwsm8,4326
27
+ django_slack_tools/slack_messages/message_templates/python.py,sha256=qFWcWJLDbs9lK42_F3-fbkH7mxwDC3TgVYtjEaZvyI0,1113
28
+ django_slack_tools/slack_messages/middlewares/__init__.py,sha256=Y1iVV37JWjQZqL5vzbVGJkhtyQFDKrZL_YSj1UHiyXs,194
29
+ django_slack_tools/slack_messages/middlewares/base.py,sha256=8s3I1e_jjDKJDgKenaKy32DwkqfiZeu5uJKpIWXRiD8,974
30
+ django_slack_tools/slack_messages/middlewares/django.py,sha256=ZCkfqlIzqai6TFOHcYuy9Hl_xO0s5OrZgXSVQ-umFXc,9290
31
+ django_slack_tools/slack_messages/migrations/0001_initial.py,sha256=NvsXJoPfG3UNEIxzioMiyjVsv0B26UDTouznZr7a_C0,11622
32
+ django_slack_tools/slack_messages/migrations/0002_default_policy.py,sha256=a1pf6bGhFszOz2awUudQnm9FyxIdWcs3ILsWCADG4YU,1145
33
+ django_slack_tools/slack_messages/migrations/0003_default_recipient.py,sha256=SqqawYxEHItmCYAgfv-EAsnc7Fxg3mJtKw6ccDCF1Eo,1153
34
+ django_slack_tools/slack_messages/migrations/0004_slackmessagingpolicy_template_type.py,sha256=u5WkhdPxzXLraw8oTvC0sBV5GUFR0fDghtoc2RvTFQU,679
35
+ django_slack_tools/slack_messages/migrations/0005_alter_slackmessagingpolicy_template_type.py,sha256=guAG77_8eDXMECE6pZKkmjrfvWflmhmVuFirTLVb3KU,1652
36
+ django_slack_tools/slack_messages/migrations/0006_alter_slackmessage_id.py,sha256=dG97L44IQRjXJ7MFH0SPzGGhV_NcaOLUemh9yiY3siI,626
37
+ django_slack_tools/slack_messages/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ django_slack_tools/slack_messages/models/__init__.py,sha256=5niO9vU-YMGRCt7wQMXbN-hSrLpJLtukMKjjv-aFeaQ,265
39
+ django_slack_tools/slack_messages/models/mention.py,sha256=ofLH4q8pzleW3ReCnD83BOOzWopNUsD0MjKkz8s7HYI,2084
40
+ django_slack_tools/slack_messages/models/message.py,sha256=iTlRGsHM0SQ1853uODqJSt6DKIdw7HFScmUSZZJeVRs,3787
41
+ django_slack_tools/slack_messages/models/message_recipient.py,sha256=rqIWfhqTQrjejRXNz2TT5JBi89zWlngaSiQ81anQCAA,1673
42
+ django_slack_tools/slack_messages/models/messaging_policy.py,sha256=FFndVT-hOJDBMCvQ8to6VARlqlpPyXPX8UKNQaVO2k0,2975
43
+ django_slack_tools/slack_messages/template_loaders/__init__.py,sha256=0RKD-AYYplt0KbkgGwEwQFj-rpfArxXLkt3fiXl-iU0,324
44
+ django_slack_tools/slack_messages/template_loaders/base.py,sha256=2I7i9UIoEk1gXCKoGFbHsOYKCKI6IBr6k_LzL1c1-mY,406
45
+ django_slack_tools/slack_messages/template_loaders/django.py,sha256=TCKyypEe17uikg0wLiiRqYO_TxvKyGpQpNYmJhFwoD4,2580
46
+ django_slack_tools/slack_messages/template_loaders/errors.py,sha256=qFw6FrObL1nAW-fE07N_leygvE1ZCEhLMiLGLMSGtG8,186
47
+ django_slack_tools/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ django_slack_tools/utils/import_helper.py,sha256=o3BhGYzPwXPNWz1bDWyTbAp0R5bSpdewgmmiob6rgIw,992
49
+ django_slack_tools/utils/repr.py,sha256=BVmm5vWb8Kws5jJygX1_VeZmjfH6IphTFVXqJMM2r7A,265
50
+ django_slack_tools/utils/django/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ django_slack_tools/utils/django/model_mixins.py,sha256=bNPx3yudzUku8TnjstestOs6YEww58FmBUypL5caYdI,634
52
+ django_slack_tools/utils/django/widgets.py,sha256=v1EorzDSDXn_ZZgBHVFYMhWPG5RsfEI3L3VFf282svg,876
53
+ django_slack_tools/utils/slack/__init__.py,sha256=rByQXL5NEZPRVVv7jdh18hVh2OBxnlym3reDKSTWYLE,86
54
+ django_slack_tools/utils/slack/misc.py,sha256=bl7xp43IsTt0FUZWfGH9kk4qYMU0UjIhuGs35zkLyyE,1099
55
+ django_slack_tools-0.3.1.dist-info/METADATA,sha256=N7Izcd6A_vZmJFnVcOhoy0t91h0MhbFbw3caxD53N1A,3354
56
+ django_slack_tools-0.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
57
+ django_slack_tools-0.3.1.dist-info/licenses/LICENSE,sha256=lPgIV-vu4gapOeftp1Dp5RsN6zlsiMiubqCNeP466hw,1067
58
+ django_slack_tools-0.3.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.26.1
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any