- Python 99.7%
- Dockerfile 0.3%
| data | ||
| src/cost_rental_bot | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| compose.dev.yml | ||
| compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
Cost Rental Bot
Monitor Cost Rental schemes across Ireland from multiple housing providers through a single, consistent interface.
Cost Rental Bot collects listings from supported providers, normalises the data into a common format, and generates reports that can be viewed from the command line or delivered through Telegram.
The project uses a provider/collector architecture, making it straightforward to support additional housing providers as they become available.
The bot is distributed as an OCI container image and can be run without installing Python or building the project locally.
Features
- Collect Cost Rental listings from multiple Irish housing providers
- Normalise provider data into a common structure
- Generate human-readable reports
- Send reports directly to Telegram
- Interactive Telegram bot
- Incremental daily scheduled reports
- Persistent per-chat notification history
- Independent schedules for multiple Telegram chats
- Private and public Telegram access modes
- Automatic provider discovery
- WordPress API support where available
- HTML scraping fallback when required
- Persistent configuration across container restarts
- Ready-to-run OCI container image
- Docker Compose deployment
Supported Providers
| Provider | Status |
|---|---|
| Affordable Homes | ✅ |
| Clúid Housing | ✅ |
| Tuath Housing | ✅ |
| Respond | ✅ |
| Circle VHA | ✅ |
Provider websites may apply their own network or geographic access restrictions. A deployment must be able to reach the supported provider websites in order to collect their listings.
Architecture
Housing Providers
│
┌──────────────┼──────────────┐
▼ ▼ ▼
WordPress HTML Parser JSON APIs
│ │ │
└──────────────┴──────────────┘
│
Provider Collectors
│
▼
Normalised Listings
│
┌────────────┴────────────┐
▼ ▼
CLI Reports Telegram Bot
│
▼
Per-chat Scheduler
Every provider is responsible for collecting and parsing its own data.
Once parsed, every listing is converted into the same internal format, allowing reports, notifications and future features to work independently from the source website.
Telegram schedules and notification history are stored per chat, allowing different chats to receive reports at different times while independently tracking previously reported schemes.
Running with Docker
Requirements
- Docker
- Docker Compose
The published container image is available from the project's Forgejo registry:
ogma.mobhru.dynv6.net/saulo/cost-rental-bot
The current stable release can be pulled with:
docker pull ogma.mobhru.dynv6.net/saulo/cost-rental-bot:latest
Versioned images are also available, for example:
docker pull ogma.mobhru.dynv6.net/saulo/cost-rental-bot:0.2.0
Using a versioned tag is recommended when you want deployments to remain pinned to a specific release.
Docker Compose
Create a compose.yml:
services:
cost-rental-bot:
image: ogma.mobhru.dynv6.net/saulo/cost-rental-bot:latest
container_name: cost-rental-bot
restart: unless-stopped
env_file:
- .env
volumes:
- cost-rental-data:/app/data
volumes:
cost-rental-data:
Create a .env file alongside it.
For a private bot:
TELEGRAM_BOT_TOKEN=...
TELEGRAM_ACCESS_MODE=private
TELEGRAM_ALLOWED_CHAT_IDS=-1001234567890,123456789
Multiple allowed chat IDs can be provided as a comma-separated list.
For a public bot:
TELEGRAM_BOT_TOKEN=...
TELEGRAM_ACCESS_MODE=public
TELEGRAM_ALLOWED_CHAT_IDS is not required in public mode.
Start the bot:
docker compose up -d
View its logs:
docker compose logs -f cost-rental-bot
Update to the latest published image:
docker compose pull
docker compose up -d
The /app/data directory is stored in the cost-rental-data Docker volume, so schedules and notification history survive container recreation and image updates.
Telegram Access
Cost Rental Bot supports two access modes.
Private mode
TELEGRAM_ACCESS_MODE=private
Only chats listed in TELEGRAM_ALLOWED_CHAT_IDS may use the bot.
For example:
TELEGRAM_ALLOWED_CHAT_IDS=-1001234567890,123456789
This can contain private chats, groups, or a mixture of both.
Private mode requires at least one allowed chat ID. The bot will refuse to start if private mode is selected without an allowlist.
Public mode
TELEGRAM_ACCESS_MODE=public
Commands are accepted from any Telegram chat that can communicate with the bot.
The allowlist is ignored in public mode.
Telegram Commands
The Telegram bot supports the following commands:
| Command | Description |
|---|---|
/report |
Generate the current Cost Rental report |
/discover |
Check Affordable Homes for providers without collectors |
/schedule |
Display the daily report schedule for the current chat |
/schedule HH:MM |
Schedule a daily report for the current chat |
/schedule off |
Disable scheduled reports for the current chat |
/schedule reset |
Clear notification history for the current chat |
/help |
Display the available commands |
Schedules are independent for each Telegram chat.
For example, one group can use:
/schedule 15:00
whilst a private chat can independently use:
/schedule 18:30
/report always generates a complete snapshot of the currently available and upcoming Cost Rental schemes.
Scheduled reports are incremental. The first scheduled report sends all currently available and upcoming schemes and establishes a per-chat notification baseline. Subsequent scheduled reports send only schemes that have appeared since the previous scheduled report.
Changing or disabling a schedule does not clear its notification history. Use /schedule reset to clear the history for the current chat. The next scheduled report will then treat all currently available and upcoming schemes as new.
Closed schemes are not stored in the notification history. If a previously closed scheme becomes available again, it can therefore be reported as new.
Scheduled reports use the Europe/Dublin timezone, automatically accounting for Irish standard time and daylight-saving changes.
Schedules and notification history are persisted across container restarts and recreation.
The scheduler deliberately does not catch up on missed executions. If the bot is not running at the scheduled time, that report is skipped and the scheduler waits for the next scheduled occurrence.
CLI
The container exposes the Cost Rental Bot CLI through its entrypoint.
Display the available commands:
docker run --rm \
ogma.mobhru.dynv6.net/saulo/cost-rental-bot:latest \
--help
Collect listings from a provider:
docker run --rm \
ogma.mobhru.dynv6.net/saulo/cost-rental-bot:latest \
collect cluid
Generate a report:
docker run --rm \
ogma.mobhru.dynv6.net/saulo/cost-rental-bot:latest \
report
Discover unsupported providers:
docker run --rm \
ogma.mobhru.dynv6.net/saulo/cost-rental-bot:latest \
discover-providers
When running commands that require Telegram configuration, pass the appropriate environment variables or use Docker Compose.
Development
Clone the repository:
git clone https://ogma.mobhru.dynv6.net/saulo/cost-rental-bot.git
cd cost-rental-bot
Create the local configuration:
cp .env.example .env
Edit it as required:
vim .env
The normal compose.yml uses the published image.
For local development, compose.dev.yml overrides it with a locally built image:
docker compose \
-f compose.yml \
-f compose.dev.yml \
up -d --build
The application can also be built directly:
docker build -t cost-rental-bot:dev .
Run the CLI from the development image:
docker run --rm \
cost-rental-bot:dev \
--help
Project Structure
src/
└── cost_rental_bot/
├── collectors/
├── models.py
├── notification_store.py
├── report.py
├── schedule_store.py
├── scheduler.py
├── telegram_bot.py
├── telegram_client.py
├── telegram_commands.py
└── ...
Each provider collector is self-contained and responsible for:
- discovering available listings
- extracting property details
- determining listing status
- returning normalised data
Scheduling and Telegram access control are independent from the provider collectors, allowing collection, reporting and delivery to evolve separately.
Adding a Provider
Supporting a new provider generally involves four steps:
- Create a new collector.
- Parse the provider's listings.
- Convert the data into the common listing model.
- Register the collector with the application.
Because each collector is isolated, adding new providers should have little or no impact on existing collectors.
Roadmap
- Multi-provider collection
- Telegram reporting
- Interactive Telegram bot
- Provider discovery
- Daily scheduled reports
- Per-chat scheduling
- Private and public Telegram access modes
- OCI container image
- Persistent Docker deployment
- Incremental scheduled notifications
- Persistent per-chat notification history
- Historical listing tracking
- Provider failure isolation
- Price change detection
- Unit tests
- Automated container builds and releases
- Web dashboard
Contributing
Issues, ideas and pull requests are welcome.
If you find a Cost Rental provider that is not yet supported, feel free to open an issue with a link to the provider's Cost Rental page.
Licence
This project is licensed under the GNU General Public License v3.0.
See LICENSE for the full licence text.
The intention is simple: if the community improves the project, those improvements should remain available to the community.