Files
NopeCharon 67f5878da4 [Webhook] Keep the HTML of the {content} placeholder intact (#562)
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 `&lt;b&gt;` tag produced an unclosed `<b>` element, escaped code
samples such as `&lt;script&gt;` became live tags, `&amp;` became a bare
`&`, and `&quot;` 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
2026-10-27 11:33:00 +01:00
..

FreshRSS Webhook Extension

License: AGPL v3 FreshRSS

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

  1. Download the extension files
  2. Upload the xExtension-Webhook folder to your FreshRSS extensions directory
  3. Enable the extension in FreshRSS admin panel under Extensions

⚙️ Configuration

Basic Setup

  1. Go to Administration → Extensions → Webhook
  2. 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:

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 DEVELOPMENT environment)
  • 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:

  1. Fork the repository
  2. Create a feature branch
  3. Follow FreshRSS coding standards
  4. Add tests for new functionality
  5. 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

📞 Support