A flexible, extensible bot for tracking updates across different content sources (manga chapters, blog posts, etc.) and sending notifications through Telegram.
- Object-oriented design with easy-to-extend base classes
- Support for multiple content sources:
- Manga chapter updates
- Blog post feeds
- Persistent storage of latest items
- Telegram notifications
- Async implementation for efficient polling
- Configurable check intervals
- Comprehensive test suite
- Secure systemd service integration
- Clone the repository
- Create a virtual environment and activate it:
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate- Install package and dependencies:
# For development (includes testing tools)
pip install -e ".[dev]"
# For production only
pip install -e .- Create a
.envfile with your configuration:
TELEGRAM_TOKEN=your_bot_token
TELEGRAM_CHAT_ID=your_chat_id
CHECK_INTERVAL=300 # Optional, defaults to 300 seconds
STORAGE_DIR=storage # Optional, defaults to 'storage'
LOG_FILE=bot.log # Optional, defaults to 'bot.log'
LOG_LEVEL=INFO # Optional, defaults to 'INFO'Run the bot directly:
python main.pyInstall and start the systemd service:
sudo ./install_service.shThis will:
- Create a virtual environment if needed
- Install dependencies
- Set up the systemd service
- Start the bot
Check service status:
systemctl status content-update-botAfter making changes to the service file:
# Reload systemd daemon
sudo systemctl daemon-reload
# Restart the service
sudo systemctl restart content-update-botView logs:
journalctl -u content-update-bot -fRun the test suite:
# Activate virtual environment first
source venv/bin/activate
# Run tests with coverage
pytest --cov=src tests/
# Run specific test file
pytest tests/test_manga_scraper.py -v
# Format code
black src/ tests/
isort src/ tests/- Create a new scraper class that inherits from
BaseScraper - Implement the required methods:
fetch_latest(): Fetch the latest itemget_item_id(): Extract unique identifierformat_notification(): Format notification messagevalidate_item(): Validate scraped item
Example:
class MyNewScraper(BaseScraper):
async def fetch_latest(self) -> Optional[ScrapedItem]:
# Implementation here
pass- Add your new scraper to the list in
main.py
src/
├── scrapers/
│ ├── base.py # Base scraper class
│ ├── manga.py # Manga-specific scraper
│ └── blog.py # Blog-specific scraper
├── storage/
│ └── handler.py # Persistent storage handling
├── notifications/
│ └── handler.py # Notification handling
└── bot/
└── manager.py # Main bot logic
- Fork the repository
- Create a feature branch
- Commit your changes
- Open a pull request
MIT License - feel free to use and modify as needed.