* Fix premature keyword filtering in Facebook marketplace scraping
Addresses a critical bug where listings were incorrectly rejected during
keyword filtering before their descriptions had been extracted from
Facebook's detail pages.
## Problem
The dual-check workflow was failing:
1. First check_listing() call: On search results with empty descriptions
2. Second check_listing() call: After get_listing_details() populates descriptions
Listings with keywords only in descriptions were being rejected prematurely,
causing false negatives for valid matches.
## Solution
- Add description_available parameter to check_listing() to control filtering
- Skip keyword filtering when descriptions haven't been fetched yet
- Maintain antikeyword filtering on available text (title-only or title+description)
- Add warning logs when description extraction fails
## Changes
- facebook.py: Add description_available parameter and conditional filtering logic
- monitor.py: Add defensive tuple unpacking for get_listing_details() return value
- Add comprehensive test suite for keyword filtering edge cases
- Fix minor formatting inconsistencies throughout codebase
## Testing
- New test suite demonstrates the bug and validates the fix
- Tests cover keyword filtering with/without descriptions
- Antikeyword filtering verified to work correctly in all cases
- All existing tests continue to pass
Fixes: #247
* Apply minor code improvements from PR feedback
- Remove redundant description_available=True parameter (uses default)
- Move self.logger check to outer if condition to avoid nested checks
These changes improve code clarity and efficiency.
* feat: add comprehensive Telegram notification support
Add complete Telegram bot integration for AI Marketplace Monitor notifications:
- Implement TelegramNotificationConfig with bot token and chat ID authentication
- Add MarkdownV2 message formatting with proper escaping for Telegram
- Implement intelligent message splitting for 4096 character limit
- Add global rate limiting (30 messages/second) with automatic retry logic
- Support for HTTP 429 handling and connection error recovery
- Add configuration validation and detailed error handling
- Include comprehensive unit tests with async operation mocking
- Add detailed setup documentation with troubleshooting guide
- Support environment variable configuration for security
- Compatible with individual users and group chats
Includes dependency: python-telegram-bot for reliable Telegram API integration
* refactor: remove redundant telegram auto-creation logic
- Remove duplicate telegram notification creation in config.py since notify_all already handles this
- Fix unnecessary else clause after early return in telegram.py
- Remove obsolete tests for auto-creation behavior
- Clean up unused imports
The notification system continues to work via the existing notify_all method which dynamically creates notification objects when user configs contain required fields.
* refactor: simplify message splitting using textwrap module
Replace manual word boundary splitting logic with Python's built-in
textwrap.wrap() function. This reduces ~30 lines of custom logic to
a single line while maintaining identical functionality.
- Use textwrap.wrap() with break_long_words=False
- Maintains word boundary splitting behavior
- All existing tests continue to pass
Addresses GitHub issue #240 by adding proper application identification
when using OpenRouter API. This ensures the application appears as
"AI Marketplace Monitor" in OpenRouter's dashboard instead of "Unknown"
and provides a direct link to the GitHub repository.
- Added X-Title header with application name
- Added HTTP-Referer header with repository URL
- Follows OpenRouter's recommended identification practices
Add proper newline spacing before "AI:" messages in all notification formats:
- Plain text: Add \n before "AI:"
- Markdown: Add \n before "**AI**:"
- HTML: Add <br> before "<b>AI</b>:"
- Email text: Add \n before "AI:"
This improves readability by separating AI comments from listing details
with appropriate whitespace in all notification channels.
- Add monitor_config: dict to key_types dictionary in test_config function
- Resolves KeyError: 'monitor_config' that was causing 9 test failures
- All CLI config tests now pass (65 passed, 1 skipped)