Metadata-Version: 2.5
Name: contentrules.slack
Version: 3.0.0
Summary: Slack content rule action for Plone
Project-URL: Homepage, https://github.com/collective/contentrules.slack
Project-URL: Documentation, https://collective.github.io/contentrules.slack
Project-URL: PyPI, https://pypi.org/project/contentrules.slack
Project-URL: Source, https://github.com/collective/contentrules.slack
Project-URL: Tracker, https://github.com/collective/contentrules.slack/issues
Author-email: Érico Andrei <ericof@plone.org>
License-Expression: GPL-2.0-only
License-File: LICENSE.GPL
License-File: LICENSE.md
Keywords: CMS,Content Rules,Plone,Python,Slack
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Plone
Classifier: Framework :: Plone :: 6.1
Classifier: Framework :: Plone :: 6.2
Classifier: Framework :: Plone :: Addon
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Requires-Dist: plone-api
Requires-Dist: plone-restapi
Requires-Dist: prettyconf
Requires-Dist: products-cmfplone>=6.1
Requires-Dist: requests
Provides-Extra: docs
Requires-Dist: graphviz; extra == 'docs'
Requires-Dist: linkify-it-py; extra == 'docs'
Requires-Dist: myst-parser; extra == 'docs'
Requires-Dist: plone-sphinx-theme; extra == 'docs'
Requires-Dist: sphinx-autobuild; extra == 'docs'
Requires-Dist: sphinx-copybutton; extra == 'docs'
Requires-Dist: sphinx-design; extra == 'docs'
Requires-Dist: sphinx-examples; extra == 'docs'
Requires-Dist: sphinx-notfound-page; extra == 'docs'
Requires-Dist: sphinx-reredirects; extra == 'docs'
Requires-Dist: sphinx-sitemap; extra == 'docs'
Requires-Dist: sphinx-tippy; extra == 'docs'
Requires-Dist: sphinxcontrib-httpdomain; extra == 'docs'
Requires-Dist: sphinxcontrib-httpexample; extra == 'docs'
Requires-Dist: sphinxcontrib-mermaid; extra == 'docs'
Requires-Dist: sphinxcontrib-video; extra == 'docs'
Requires-Dist: sphinxcontrib-youtube; extra == 'docs'
Requires-Dist: sphinxext-opengraph; extra == 'docs'
Requires-Dist: vale; extra == 'docs'
Provides-Extra: release
Requires-Dist: zest-pocompile; extra == 'release'
Requires-Dist: zest-releaser[recommended]; extra == 'release'
Requires-Dist: zestreleaser-towncrier; extra == 'release'
Provides-Extra: test
Requires-Dist: horse-with-no-namespace; extra == 'test'
Requires-Dist: mypy; extra == 'test'
Requires-Dist: plone-app-testing; extra == 'test'
Requires-Dist: plone-classicui; extra == 'test'
Requires-Dist: plone-restapi[test]; extra == 'test'
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-cov; extra == 'test'
Requires-Dist: pytest-plone>=1.1.0; extra == 'test'
Requires-Dist: types-requests; extra == 'test'
Description-Content-Type: text/markdown

# contentrules.slack

[![PyPI](https://img.shields.io/pypi/v/contentrules.slack)](https://pypi.org/project/contentrules.slack/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/contentrules.slack)](https://pypi.org/project/contentrules.slack/)
[![PyPI - Plone Versions](https://img.shields.io/pypi/frameworkversions/plone/contentrules.slack)](https://pypi.org/project/contentrules.slack/)
[![PyPI - License](https://img.shields.io/pypi/l/contentrules.slack)](https://pypi.org/project/contentrules.slack/)
[![CI](https://github.com/collective/contentrules.slack/actions/workflows/main.yml/badge.svg)](https://github.com/collective/contentrules.slack/actions/workflows/main.yml)
[![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://collective.github.io/contentrules.slack/)

**Post a message to Slack whenever something happens in your Plone site.**

contentrules.slack adds a **Post a message to Slack** action to Plone's content rules.
Pick any event Plone content rules support — a page is published, content is removed, a user logs in — and your team hears about it in the Slack channel of your choice, with the details that matter.

![A Slack message posted by Plone, announcing that a user logged in](https://raw.githubusercontent.com/collective/contentrules.slack/main/docs/src/_static/images/classic-ui/Screenshot-07.png)

## Why use it

- **No code.** Site administrators set up notifications from the Content Rules control panel, in Volto or Classic UI.
- **Messages with context.** Use `${...}` variables, such as `${title}`, `${absolute_url}`, `${review_state_title}`, or `${user_fullname}`, to say what changed, where, and who changed it.
- **Scoped to where it matters.** Assign a rule to the whole site, or only to one folder.
- **Never slows editors down.** Messages are sent in the background, so publishing never waits for Slack, and never fails because of it.
- **Safe for staging.** Set one environment variable to silence every notification on a development or staging copy of your site.

## Features

- A content rule action, available for every triggering event and content type.
- Slack message attachments with pretext, title and link, text, color, and a table of fields.
- Failed deliveries logged to the Plone log, without leaking the webhook address.
- A Python API, `notify_slack`, to post to Slack from your own code.
- A user interface in English, Brazilian Portuguese, German, and Spanish.

## Compatibility

| contentrules.slack | Plone | Python |
|---|---|---|
| 3.x | 6.2 | 3.10 to 3.14 |
| 3.x | 6.1 | 3.10 to 3.13 |
| 2.x | 6.0 | 3.8 to 3.11 |

## Installation

Add `contentrules.slack` to the dependencies of your Plone project, for example in its `pyproject.toml`:

```toml
[project]
dependencies = [
    "Products.CMFPlone",
    "contentrules.slack",
]
```

Or install it with pip, in the same Python environment as Plone:

```shell
pip install contentrules.slack
```

Restart Plone.
There is nothing to activate in the Add-ons control panel: **Post a message to Slack** is now available in **Site Setup → Content Rules**.

## Quick start

1. Create an [incoming webhook](https://docs.slack.dev/messaging/sending-messages-using-incoming-webhooks/) in Slack.
2. In **Site Setup → Content Rules**, add a rule, and choose its triggering event.
3. Add the **Post a message to Slack** action, and paste the webhook address.
4. Assign the rule to the whole site, or to a folder.

The documentation walks you through each step, with screenshots, for [Volto](https://collective.github.io/contentrules.slack/how-to/volto.html) and [Classic UI](https://collective.github.io/contentrules.slack/how-to/classic-ui.html).

## Configuration

| Environment variable | Effect |
|---|---|
| `DEACTIVATE_SLACK_NOTIFICATION` | Set to `deactivate` to stop the whole instance from posting to Slack. |
| `SLACK_WEBHOOK_URL` | Webhook used by `notify_slack` calls that do not pass one. |

Both are read once, at startup.
See the [configuration reference](https://collective.github.io/contentrules.slack/reference/configuration.html) for details.

## Documentation

The full documentation is at **https://collective.github.io/contentrules.slack/**.

- [How-to guides](https://collective.github.io/contentrules.slack/how-to/index.html): install the add-on, and create rules in Volto or Classic UI.
- [Reference](https://collective.github.io/contentrules.slack/reference/index.html): every field of the action, the settings, and the Python API.
- [Explanation](https://collective.github.io/contentrules.slack/explanation/index.html): how messages are delivered, and what happens when Slack fails.

## Contributing

- [Source code](https://github.com/collective/contentrules.slack)
- [Issue tracker](https://github.com/collective/contentrules.slack/issues)
- [Contributing guide](https://collective.github.io/contentrules.slack/project/contributing.html)

To set up a development environment, you need [uv](https://docs.astral.sh/uv/), Make, and Git.

```shell
git clone https://github.com/collective/contentrules.slack.git
cd contentrules.slack
make install
make test
```

## License

This project is licensed under the GNU General Public License, version 2.

## Credits

Originally made in Berlin by Briefy and Pendect.

Now maintained by the [Plone Collective](https://github.com/collective).


---

# Changelog

<!--
   You should *NOT* be adding new change log entries to this file.
   You should create a file in the news directory instead.
   For helpful instructions, please see:
   https://github.com/plone/plone.releaser/blob/master/ADD-A-NEWS-ITEM.rst
-->

<!-- towncrier release notes start -->

## 3.0.0 (2026-09-29)


### Breaking

- Drop support for Plone 6.0 and Python 3.8 and 3.9. This package now requires Plone 6.1 or later, and Python 3.10 or later. @ericof [#14](https://github.com/collective/contentrules.slack/issues/14)


### Feature

- Log failed Slack notifications -- an error status, a timeout or a connection error -- to the `contentrules.slack` logger, instead of losing them in the background thread. The webhook URL is left out of the log message. @ericof [#17](https://github.com/collective/contentrules.slack/issues/17)


### Bugfix

- Add the missing space between the two sentences of the "Fields" help text, and update the translations to match. @ericof [#18](https://github.com/collective/contentrules.slack/issues/18)


### Internal

- Modernize the package with the cookieplone `backend_addon` template: `pyproject.toml` with hatchling, and a Makefile using uv and mxdev. Declare the `prettyconf` dependency explicitly. @ericof [#14](https://github.com/collective/contentrules.slack/issues/14)
- Add type hints and reStructuredText docstrings to the whole codebase, and check types with `mypy` against `plone-stubs` (`make mypy`, also run by `make lint`). @ericof [#15](https://github.com/collective/contentrules.slack/issues/15)
- Label Dependabot pull requests, and exempt them from the change log check. @ericof [#20](https://github.com/collective/contentrules.slack/issues/20)


### Documentation

- Rewrite the documentation following the Diátaxis framework, with how-to guides, a reference for the action, its configuration and its Python API, and an explanation of how messages are delivered. Publish it again on GitHub Pages, and rewrite the README for PyPI. @ericof [#19](https://github.com/collective/contentrules.slack/issues/19)


### Tests

- Reorganize the test suite, add end-to-end tests running a content rule with a Slack action on a real event, and require at least 95% test coverage. @ericof [#16](https://github.com/collective/contentrules.slack/issues/16)

## 2.0.2 (2023-04-04)


- Use `requests` instead of `httpx`, as the former is already distributed with Plone.
  [ericof]

- Update Sphinx theme used in the documentation
  [ericof]

## 2.0.1 (2023-03-10)


- Use [`pytest_plone`](https://pypi.org/project/pytest-plone/)
  [ericof]

- Deploy documentation to https://collective.github.io/contentrules.slack
  [ericof]



## 2.0.0 (2023-02-07)

- Use `pytest` instead of `unittest`
  [ericof]

- Drop dependency on `ftw.slacker`
  [ericof]

- Drop support to Plone 5.2
  [ericof]

- Support to Plone 6.0, Python 3.8 to 2.11
  [ericof]

- Update documentation
  [ericof]


## 1.0.1 (2020-04-25)

- Fix "TypeError: expected string or bytes-like object" when one attribute of action is not set.
  [ericof]


## 1.0.0 (2019-11-28)

- Add Plone 5.2 / Python 3 support.
  [ericof]

- Drop Python 2.7 support.
  [ericof]


## 1.0.0a1 (2017-10-17)

- Initial release.
  [ericof]
