The `{content}` placeholder is documented as the article content in HTML
format, but it was passed through `htmlspecialchars_decode()` like the
plain-text placeholders. `FreshRSS_Entry::content()` already returns
HTML, so decoding it turned escaped text into markup: an article about
the `<b>` tag produced an unclosed `<b>` element, escaped code
samples such as `<script>` became live tags, `&` became a bare
`&`, and `"` could end a double-quoted attribute early.
Insert the content as is. The plain-text placeholders (`{title}`,
`{author}`, `{url}`, ...) are still decoded, which is correct for them.
Also fix the README, which documented `{date}`, `{date_timestamp}` and
`{thumbnail_url}` placeholders that have never existed in the extension
and are sent literally. Document `{date_published}`, `{date_received}`,
`{date_modified}` and `{date_user_modified}` instead, like the
configuration page does, and use them in the examples.
Bump the extension version to 0.2.6.
Fixes #560
6.2 KiB
FreshRSS Webhook Extension
A powerful FreshRSS extension that automatically sends webhook notifications when RSS entries match configured search filters. Perfect for integrating with Discord, Slack, Telegram, or any service that supports webhooks.
🚀 Features
- Automated Notifications: Automatically sends webhooks when new RSS entries match your search filters
- Search Filters: FreshRSS native search filter syntax for precise matching
- Multiple HTTP Methods: Supports GET, POST, PUT
- Configurable Formats: Send data as JSON or form-encoded
- Template System: Customizable webhook payloads with placeholders
- Error Handling: Robust error handling with graceful fallbacks
- Test Functionality: Built-in test feature to verify webhook configuration
📋 Requirements
- FreshRSS 1.28.2+
🔧 Installation
- Download the extension files
- Upload the
xExtension-Webhookfolder to your FreshRSSextensionsdirectory - Enable the extension in FreshRSS admin panel under Extensions
⚙️ Configuration
Basic Setup
- Go to Administration → Extensions → Webhook
- Configure the following settings:
Search Filter
Use FreshRSS search filter syntax to match entries. Each line is an OR condition — if any line matches, the webhook fires. Leave empty to match all entries.
intitle:breaking news
intitle:security alert
#your-project-name
Ignore updated articles
FreshRSS also processes articles it already knows when their content changes in the feed. Enable this option to send the webhook only once per article, and not again on such updates.
Webhook Settings
- Webhook URL: Your webhook endpoint URL
- HTTP Method: Choose from GET, POST, PUT, DELETE, etc.
- Body Type: JSON or Form-encoded
- Headers: Custom HTTP headers (one per line)
Webhook Body Template
Customize the webhook payload using placeholders:
{
"title": "{title}",
"feed": "{feed_name}",
"url": "{url}",
"content": "{content}",
"published": "{date_published}",
"author": "{author}",
"tags": "{tags}",
"user": "{user}"
}
Available Placeholders
| Placeholder | Description |
|---|---|
{title} |
Article title |
{url} |
Article URL |
{content} |
Article content (HTML) |
{date_published} |
Publication date (ISO 8601) |
{date_received} |
Date received by FreshRSS (ISO 8601) |
{date_modified} |
Last modified date (ISO 8601, null if never modified) |
{date_user_modified} |
Last user-modified date (ISO 8601, null if never modified) |
{author} |
Article authors |
{feed_name} |
Feed name |
{feed_url} |
Feed URL |
{tags} |
Article tags (separated by " #") |
{user} |
Username in FreshRSS |
🎯 Use Cases
Discord Webhook
{
"content": "New article: **{title}**",
"embeds": [{
"title": "{title}",
"url": "{url}",
"description": "{content}",
"color": 3447003,
"footer": {
"text": "{feed_name}"
}
}]
}
Slack Webhook
{
"text": "New article from {feed_name}",
"attachments": [{
"title": "{title}",
"title_link": "{url}",
"text": "{content}",
"color": "good"
}]
}
Custom API Integration
{
"event": "new_article",
"data": {
"title": "{title}",
"url": "{url}",
"feed": "{feed_name}",
"published": "{date_published}"
}
}
🔍 Search Filters
The extension uses FreshRSS search filter syntax to match entries. Examples:
intitle:security
inurl:example.com
author:John
#breaking-news
intitle:urgent OR intitle:critical
intitle:release -intitle:beta
🛠️ Advanced Configuration
Custom Headers
Add authentication or custom headers:
Authorization: Bearer your-token-here
X-Custom-Header: custom-value
User-Agent: FreshRSS-Webhook/1.0
Error Handling
- Failed webhooks are logged for debugging
- Network timeouts are handled gracefully
- Invalid configurations are validated
Performance
- Only sends webhooks when filters match
- Efficient filter evaluation via FreshRSS core
- Minimal impact on RSS processing
🐛 Troubleshooting
Common Issues
Webhooks not sending:
- Check that a search filter is configured (or leave empty to match all)
- Verify webhook URL is accessible
- Check the FreshRSS logs for
[Webhook]entries
Filter not matching:
- Try simple filters first (e.g.,
intitle:test) - Refer to the FreshRSS filter documentation for syntax
Authentication errors:
- Check custom headers configuration
- Verify webhook endpoint accepts your format
Debugging
The extension logs to the FreshRSS log file with the [Webhook] prefix:
- Debug level: filter matches, HTTP requests sent (visible in
DEVELOPMENTenvironment) - Warning level: errors during article processing or failed requests (always visible)
📝 Changelog
Version 0.1.1
- Initial release
- Automated webhook notifications
- Pattern matching in multiple fields
- Configurable HTTP methods and formats
- Comprehensive error handling
- Template-based webhook payloads
🤝 Contributing
This extension was developed to address FreshRSS Issue #1513.
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Follow FreshRSS coding standards
- Add tests for new functionality
- Submit a pull request
📄 License
This extension is licensed under the GNU Affero General Public License v3.0.
🙏 Acknowledgments
- FreshRSS development team for the excellent extension system
- Community members who requested and tested this feature
- Contributors to the original feature request