diff --git a/.env.example b/.env.example index defc94c..36459b6 100644 --- a/.env.example +++ b/.env.example @@ -2,7 +2,7 @@ # GitHub Personal Access Token with 'user' and 'read:org' scopes # Create at: https://github.com/settings/tokens/new -GITHUB_TOKEN=your_github_personal_access_token_here +# GITHUB_TOKEN=your_github_personal_access_token_here # Note: GITHUB_TOKEN is not used by the current bot script. # GitHub Webhook Secret for verifying webhook signatures # Set this when configuring the webhook in your GitHub repository settings @@ -17,4 +17,26 @@ TELEGRAM_CHAT_ID=your_telegram_chat_id_here # Webhook server configuration WEBHOOK_HOST=0.0.0.0 -WEBHOOK_PORT=5000 \ No newline at end of file +WEBHOOK_PORT=5000 + +# --- Optional: Binance Payment Alerts --- +# Binance API Credentials +# Create at: https://www.binance.com/en/my/settings/api-management +BINANCE_API_KEY=your_binance_api_key_here +BINANCE_API_SECRET=your_binance_api_secret_here +# Interval in seconds to poll Binance API for new payments +BINANCE_POLL_INTERVAL=300 + +# --- Optional: IMAP Email Payment Alerts (for UPI, HDFC Bank, etc.) --- +# IMAP Server Details for reading payment notification emails +IMAP_HOST=your_imap_server_host_here +IMAP_PORT=993 # Common port for IMAP SSL, use 143 for non-SSL if required +IMAP_USER=your_imap_username_here +IMAP_PASSWORD=your_imap_password_here +IMAP_MAILBOX=INBOX # Mailbox to monitor (e.g., INBOX, or a specific folder) +# Interval in seconds to poll IMAP server +IMAP_POLL_INTERVAL=600 +# Optional: Email sender or subject keywords to help identify relevant emails +# These are case-insensitive and will be checked if present. +UPI_EMAIL_SENDER_FILTER= # e.g., upi@examplebank.com or "UPI Transaction" +HDFC_EMAIL_SENDER_FILTER= # e.g., alerts@hdfcbank.com or "HDFC Credit Card" diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 3acc41a..6ccc76b 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,157 +1,168 @@ -# GitHub Sponsors Webhook Bot Architecture +# Multi-Source Payment Alert Bot Architecture -This document provides an overview of the GitHub Sponsors Webhook Bot architecture, explaining the design decisions, component interactions, and data flow. +This document provides an overview of the Multi-Source Payment Alert Bot architecture, explaining the design decisions, component interactions, and data flow. ## System Overview -The GitHub Sponsors Webhook Bot is designed to: +The Multi-Source Payment Alert Bot is designed to: -1. Receive webhook events from GitHub when a new sponsorship is created -2. Verify the authenticity of these webhook events -3. Extract relevant information from the webhook payload -4. Format and send notifications to a Telegram chat +1. **Receive GitHub Sponsors Webhook Events**: + * Process webhook events from GitHub when a new sponsorship is created. + * Verify the authenticity of these webhook events. + * Extract relevant information from the webhook payload. +2. **Poll Binance for Payments**: + * Connect to the Binance API periodically. + * Fetch new cryptocurrency deposit information. + * Fetch completed P2P payment receipts. +3. **Poll IMAP Server for Email Payments**: + * Connect to a configured IMAP email server periodically. + * Fetch new, unread emails. + * Parse emails to identify and extract details from UPI and HDFC Bank payment notifications. +4. **Send Notifications**: + * Format and send notifications for all payment types to a configured Telegram chat. -The system is built as a single Python application that combines a webhook server with Telegram bot functionality. +The system is built as a single Python application that combines a webhook server (for GitHub), polling mechanisms for Binance and IMAP, and Telegram bot functionality. ## Component Architecture ``` -┌─────────────────────────────────────────────────────────┐ -│ │ -│ GitHub Sponsors Webhook Bot │ -│ │ -├─────────────┬───────────────────────┬──────────────────┤ -│ │ │ │ -│ Flask │ Webhook │ Telegram │ -│ Web Server │ Handler │ Bot API │ -│ │ │ │ -└─────┬───────┴───────────┬───────────┴────────┬─────────┘ - │ │ │ - │ │ │ - ▼ ▼ ▼ -┌─────────────┐ ┌───────────────┐ ┌──────────────┐ -│ │ │ │ │ │ -│ GitHub │ │ Webhook │ │ Telegram │ -│ API │ │ Events │ │ Chat │ -│ │ │ │ │ │ -└─────────────┘ └───────────────┘ └──────────────┘ + External Systems + │ + ▼ + ┌─────────────────────┐ ┌───────────────────┐ ┌───────────────────────────┐ + │ GitHub Webhooks │ │ Binance API │ │ IMAP Email Server │ + │ (Sponsors Events) │ │ (Deposits, P2P) │ │ (UPI/HDFC Notifications) │ + └──────────┬──────────┘ └─────────┬─────────┘ └────────────┬────────────┘ + │ │ │ + │ (HTTPS POST) │ (API Calls) │ (IMAP Commands) + ▼ ▼ ▼ +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ Multi-Source Payment Alert Bot │ +│ (github_sponsors_bot.py) │ +│ │ +├─────────────────────────┬──────────────────────────┬────────────────────────────────────┤ +│ │ │ │ +│ Flask Web Server │ Payment Source Modules │ Telegram Bot │ +│ (Webhook Endpoint) │ (Polling & Parsing) │ (Notification & Commands) │ +│ │ │ │ +└───────────┬─────────────┴─────────────┬────────────┴───────────────────┬────────────────┘ + │ │ │ + │ (Webhook Data) │ (Payment Data) │ (Formatted Messages) + ▼ ▼ ▼ +┌─────────────────────────┐ ┌──────────────────────────┐ ┌───────────────────────────────────┐ +│ Webhook Handler │ │ BinanceAlerts Module │ │ Telegram API │ +│ - Signature Verification│ │ - API Client │ │ (python-telegram-bot) │ +│ - GitHub Event Parsing │ │ - Deposit/P2P Fetching │ └───────────────────┬───────────────┘ +│ - Message Formatting │ │ - Message Formatting │ │ +└─────────────────────────┘ └──────────────────────────┘ │ + ┌──────────────────────────┐ │ + │ ImapAlerts Module │ │ + │ - IMAP Client │ │ + │ - Email Fetching/Parsing │ │ + │ - Message Formatting │ │ + └──────────────────────────┘ │ + │ + ▼ + ┌─────────────────┐ + │ Telegram Chat │ + │ (User/Group) │ + └─────────────────┘ ``` ### Core Components -1. **Flask Web Server** - - Provides HTTP endpoints for receiving webhook events - - Handles routing and request/response processing - - Exposes health check endpoint for monitoring +1. **Main Application (`github_sponsors_bot.py`)**: + * **Flask Web Server**: + * Provides HTTP endpoints (e.g., `/webhook/github`) for receiving GitHub Sponsors webhook events. + * Handles routing and request/response processing. + * Exposes a health check endpoint (`/health`). + * **TelegramBot Class**: + * Manages all communication with the Telegram API using `python-telegram-bot`. + * Sends formatted notifications to the configured chat. + * Handles Telegram commands (e.g., `/start`, `/help`, `/status`). + * Manages bot lifecycle (initialization, polling for commands, shutdown). + * **Polling Orchestration**: + * Initializes and manages separate threads for polling Binance and IMAP payment sources at configured intervals. + * **Configuration Management**: + * Loads all necessary credentials and settings from environment variables using `python-dotenv`. -2. **Webhook Handler** - - Verifies webhook signatures using HMAC-SHA256 - - Parses and validates webhook payloads - - Extracts relevant sponsorship information - - Formats notification messages - -3. **Telegram Bot API** - - Manages communication with the Telegram API - - Sends formatted notifications to the configured chat - - Handles command processing for bot interactions - - Manages bot lifecycle (initialization, polling, shutdown) +2. **Payment Source Modules (`payment_sources/`)**: + * **`BinanceAlerts` Module (`binance_alerts.py`)**: + * Responsible for interacting with the Binance API. + * Fetches new cryptocurrency deposit data. + * Fetches completed P2P payment receipts. + * Formats Binance-specific payment data into notification messages. + * Manages Binance API credentials securely. + * Includes logic to avoid sending duplicate alerts (placeholder). + * **`ImapAlerts` Module (`imap_alerts.py`)**: + * Connects to a specified IMAP email server. + * Fetches new/unread emails from the configured mailbox. + * Parses email content (subject, sender, body) to identify and extract details from UPI and HDFC Bank payment notifications. This logic is highly dependent on email formats and may require custom regex/string parsing. + * Formats extracted email payment data into notification messages. + * Manages IMAP credentials securely. ## Data Flow -1. **Webhook Reception** - - GitHub sends a POST request to the `/webhook/github` endpoint - - The request includes headers with event type and signature - - The payload contains details about the sponsorship event +1. **GitHub Sponsors Webhook**: + * GitHub sends a POST request to `/webhook/github`. + * The Flask server routes it to the `github_webhook` handler. + * **Signature Verification**: The handler verifies the `X-Hub-Signature-256` using the `GITHUB_WEBHOOK_SECRET`. Invalid requests are rejected. + * **Event Processing**: For valid 'sponsorship' events (action: 'created'), the payload is parsed by `format_sponsor_message`. + * **Notification**: The formatted message is sent via the `TelegramBot` instance. -2. **Signature Verification** - - The webhook handler extracts the signature from the headers - - It computes an HMAC-SHA256 hash of the request body using the webhook secret - - It compares the computed hash with the provided signature - - If they don't match, the request is rejected +2. **Binance Payment Polling**: + * A dedicated thread periodically calls `binance_alerter.check_for_new_payments()`. + * The `BinanceAlerts` module connects to the Binance API using `BINANCE_API_KEY` and `BINANCE_API_SECRET`. + * It fetches deposit history and P2P trade history. + * New/relevant transactions are identified (logic to prevent duplicates is needed). + * Data is formatted by `format_deposit_message` or `format_p2p_message`. + * **Notification**: The formatted message is sent via the `TelegramBot` instance. -3. **Event Processing** - - For valid requests, the event type is checked - - For 'sponsorship' events with 'created' action, the payload is processed - - Relevant information (sponsor name, amount, tier, etc.) is extracted - - A formatted message is created - -4. **Notification Delivery** - - The formatted message is sent to the Telegram API - - The message is delivered to the configured chat ID - - Delivery status is logged +3. **IMAP Email Polling (UPI/HDFC)**: + * A dedicated thread periodically calls `imap_alerter.check_for_new_emails()`. + * The `ImapAlerts` module connects to the IMAP server using `IMAP_HOST`, `IMAP_USER`, `IMAP_PASSWORD`, etc. + * It fetches new/unread emails from `IMAP_MAILBOX`. + * Emails are filtered (optionally by sender/subject) and parsed by `parse_payment_email` to extract UPI/HDFC transaction details. + * Extracted data is formatted by `format_email_payment_message`. + * **Notification**: The formatted message is sent via the `TelegramBot` instance. ## Security Considerations -1. **Webhook Signature Verification** - - All webhook requests are verified using HMAC-SHA256 signatures - - This ensures that only GitHub can send valid webhook events - - The webhook secret is stored securely as an environment variable - -2. **Environment Variables** - - Sensitive information (tokens, secrets) is stored in environment variables - - These are never logged or exposed in responses - - The .env file is excluded from version control via .gitignore - -3. **Docker Security** - - The application runs as a non-root user in Docker - - Only necessary ports are exposed - - Dependencies are pinned to specific versions +1. **Webhook Signature Verification**: Ensures GitHub webhook authenticity. +2. **Environment Variables**: All sensitive data (API keys, tokens, passwords, secrets) are stored in environment variables and loaded via `.env` (which is gitignored). +3. **Binance API Security**: + * API keys should be configured with minimal necessary permissions (e.g., read-only for transactions). + * Avoid enabling trading or withdrawal permissions unless essential. +4. **IMAP Security**: + * Uses IMAP SSL/TLS by default (port 993). + * IMAP credentials should be for a dedicated or restricted-access email account if possible. +5. **Docker Security**: If used, the application should run as a non-root user, expose only necessary ports, and pin dependencies. ## Performance Considerations -1. **Webhook Processing** - - Webhook processing is designed to be lightweight and fast - - Responses are returned quickly to acknowledge receipt - - Processing happens synchronously to ensure delivery order - -2. **Error Handling** - - Comprehensive error handling prevents crashes - - Failed webhook processing doesn't affect future events - - All errors are logged for debugging - -3. **Scalability** - - The application can be deployed behind a load balancer for horizontal scaling - - Stateless design allows for multiple instances - - Can be deployed in containerized environments like Kubernetes +1. **Webhook Processing**: Designed to be lightweight and respond quickly. +2. **Polling Intervals**: `BINANCE_POLL_INTERVAL` and `IMAP_POLL_INTERVAL` should be set to reasonable values to balance responsiveness with API/server load. +3. **Email Parsing**: Complex regex or inefficient string operations in `imap_alerts.py` could become a bottleneck if email volume is high or emails are very large. Optimize parsing logic. +4. **Error Handling**: Robust error handling within polling loops and API interactions prevents crashes. +5. **Threading**: Background tasks (polling) are handled in separate threads to prevent blocking the main application (Flask server and Telegram command polling). ## Configuration -The application is configured through environment variables: - -- `GITHUB_WEBHOOK_SECRET`: Secret for verifying webhook signatures -- `TELEGRAM_TOKEN`: Telegram Bot API token -- `TELEGRAM_CHAT_ID`: Telegram chat ID to send notifications to -- `WEBHOOK_HOST`: Host to bind the webhook server to (default: 0.0.0.0) -- `WEBHOOK_PORT`: Port to bind the webhook server to (default: 5000) +The application is configured through environment variables, detailed in `.env.example` and the main `README.md`. This includes credentials for GitHub, Telegram, Binance, and IMAP, as well as polling intervals and server settings. ## Testing Strategy -1. **Unit Testing** - - Individual components are tested in isolation - - Mocks are used for external dependencies - -2. **Integration Testing** - - The `test_webhook.py` script simulates GitHub webhook events - - This tests the full flow from webhook reception to notification - -3. **Manual Testing** - - The README includes instructions for manual testing - - GitHub's webhook delivery replay feature can be used for testing +1. **Unit Testing**: Individual modules and functions (e.g., message formatters, parsing logic) should be tested in isolation, mocking external API/IMAP calls. +2. **Integration Testing**: + * GitHub Webhook: `test_webhook.py` script. + * Binance/IMAP: Standalone test blocks within `binance_alerts.py` and `imap_alerts.py` can be used with test credentials or mocked responses. +3. **Manual Testing**: End-to-end testing by triggering real events or sending test emails. ## Future Enhancements -1. **Additional Notification Channels** - - Support for other messaging platforms (Slack, Discord, etc.) - - Email notifications - -2. **Enhanced Filtering** - - Filter notifications based on sponsorship tier - - Custom notification templates per tier - -3. **Analytics** - - Track sponsorship statistics - - Generate reports on sponsorship activity - -4. **Admin Interface** - - Web interface for configuration and monitoring - - Real-time dashboard of sponsorship activity \ No newline at end of file +1. **Persistent State for Polling**: For Binance and IMAP, implement a persistent way (e.g., small DB, file) to store IDs of processed transactions/emails to robustly prevent duplicate alerts across bot restarts. +2. **Advanced Email Parsing**: Use more sophisticated email parsing libraries or techniques if regex becomes too complex for UPI/HDFC emails. +3. **More Notification Channels**: Support Slack, Discord, etc. +4. **Admin Interface**: A simple web UI for status monitoring or configuration. +5. **Scheduler**: Replace basic threading with a more robust scheduler like `APScheduler` for polling tasks. diff --git a/README.md b/README.md index ce757dc..84f204a 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,17 @@ -# GitHub Sponsors Webhook Bot +# GitHub Sponsors & Multi-Source Payment Alert Bot [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Python Version](https://img.shields.io/badge/python-3.7%2B-blue)](https://www.python.org/downloads/) [![Docker](https://img.shields.io/badge/docker-supported-blue)](https://www.docker.com/) -A webhook bot that sends instant Telegram notifications whenever you receive a payment through GitHub Sponsors. Get real-time alerts with complete transaction details directly to your Telegram account. +A versatile bot that sends instant Telegram notifications for: +- GitHub Sponsors payments. +- Binance cryptocurrency deposits and P2P payment receipts. +- UPI and HDFC Bank transactions (via email parsing). -![GitHub Sponsors Webhook Bot](https://via.placeholder.com/800x400?text=GitHub+Sponsors+Webhook+Bot) +Get real-time alerts with complete transaction details directly to your Telegram account. + +![Multi-Source Payment Alert Bot](https://via.placeholder.com/800x400?text=Multi-Source+Payment+Alert+Bot) ## 📋 Table of Contents @@ -17,7 +22,9 @@ A webhook bot that sends instant Telegram notifications whenever you receive a p - [Option 2: Manual Installation](#option-2-manual-installation) - [Configuration](#-configuration) - [Environment Variables](#environment-variables) - - [GitHub Webhook Setup](#github-webhook-setup) + - [GitHub Webhook Setup (for GitHub Sponsors)](#github-webhook-setup-for-github-sponsors) + - [Binance API Setup (for Binance Alerts)](#binance-api-setup-for-binance-alerts) + - [IMAP Email Setup (for UPI/HDFC Alerts)](#imap-email-setup-for-upihdfc-alerts) - [Telegram Bot Setup](#telegram-bot-setup) - [Usage](#-usage) - [Running the Bot](#running-the-bot) @@ -33,24 +40,38 @@ A webhook bot that sends instant Telegram notifications whenever you receive a p ## 🚀 Features -- **Real-time Notifications**: Receive immediate alerts when someone sponsors you on GitHub -- **Complete Transaction Details**: Get sponsor name, amount, tier selected, and timestamp -- **Secure Webhook Integration**: Verify webhook signatures for secure communication -- **Single-File Design**: All functionality in one Python file for simplicity -- **Docker Support**: Easy deployment with Docker -- **Customizable**: Configure to meet your specific needs -- **Lightweight**: Minimal resource requirements -- **Open Source**: MIT licensed, free to use and modify +- **Real-time GitHub Sponsors Notifications**: Immediate alerts for new GitHub sponsorships. +- **Binance Payment Alerts**: + - Notifications for new cryptocurrency deposits. + - Alerts for completed P2P payment receipts. +- **UPI & HDFC Bank Alerts (via Email Parsing)**: + - Parses emails from a configured IMAP account to detect and notify about UPI and HDFC Bank transactions. + - Customizable sender/subject filters for email identification. +- **Complete Transaction Details**: Get sponsor name, amount, tier, payment source, transaction IDs, and timestamps. +- **Secure Webhook Integration**: Verifies GitHub webhook signatures. +- **Secure Credential Management**: Uses environment variables for API keys and sensitive data. +- **Modular Design**: Payment sources are handled by separate modules for easy extension. +- **Docker Support**: Easy deployment with Docker. +- **Customizable**: Configure to meet your specific needs. +- **Lightweight**: Minimal resource requirements. +- **Open Source**: MIT licensed, free to use and modify. ## 📋 Prerequisites Before you begin, ensure you have the following: - Python 3.7 or higher -- A GitHub account with Sponsors enabled - A Telegram account -- A publicly accessible server to receive webhooks (or use a service like ngrok for testing) - Docker (optional, for containerized deployment) +- **For GitHub Sponsors Alerts**: + - A GitHub account with Sponsors enabled. + - A publicly accessible server to receive webhooks (or use a service like ngrok for testing). +- **For Binance Alerts (Optional)**: + - A Binance account. + - Binance API Key and Secret. +- **For UPI/HDFC Email Alerts (Optional)**: + - An email account that receives UPI/HDFC payment notifications. + - IMAP access details for that email account (host, port, username, password). ## 🔧 Installation @@ -60,7 +81,7 @@ The easiest way to get started is using Docker: 1. Clone this repository: ```bash - git clone https://github.com/overspend1/github-sponsors-webhook-bot.git + git clone https://github.com/yourusername/github-sponsors-webhook-bot.git cd github-sponsors-webhook-bot ``` @@ -69,12 +90,12 @@ The easiest way to get started is using Docker: cp .env.example .env ``` -3. Edit the `.env` file with your credentials (see [Configuration](#-configuration) section) +3. Edit the `.env` file with your credentials (see [Configuration](#-configuration) section). 4. Build and run the Docker container: ```bash - docker build -t github-sponsors-bot . - docker run -d -p 5000:5000 --name sponsors-bot --env-file .env github-sponsors-bot + docker build -t payment-alert-bot . + docker run -d -p 5000:5000 --name payment-alert-bot --env-file .env payment-alert-bot ``` ### Option 2: Manual Installation @@ -83,19 +104,21 @@ If you prefer to run the bot without Docker: 1. Clone this repository: ```bash - git clone https://github.com/overspend1/github-sponsors-webhook-bot.git + git clone https://github.com/yourusername/github-sponsors-webhook-bot.git cd github-sponsors-webhook-bot ``` 2. Create a virtual environment: ```bash - python -m venv venv + python3 -m venv venv # Or use 'python' if 'python3' is not available source venv/bin/activate # On Windows: venv\Scripts\activate ``` 3. Install dependencies: ```bash pip install -r requirements.txt + # You might need to install python-binance if not already included + # pip install python-binance ``` 4. Create a `.env` file based on the example: @@ -103,51 +126,91 @@ If you prefer to run the bot without Docker: cp .env.example .env ``` -5. Edit the `.env` file with your credentials (see [Configuration](#-configuration) section) +5. Edit the `.env` file with your credentials (see [Configuration](#-configuration) section). 6. Run the bot: ```bash - python github_sponsors_bot.py + python3 github_sponsors_bot.py # Or use 'python' ``` ## ⚙️ Configuration ### Environment Variables -The bot requires the following environment variables to be set in your `.env` file: +The bot requires various environment variables to be set in your `.env` file. Refer to the [`.env.example`](.env.example) file for a complete list and descriptions. Key variables include: +**Core:** | Variable | Description | Example | -|----------|-------------|--------| -| `GITHUB_WEBHOOK_SECRET` | Secret for verifying GitHub webhook signatures | `your_webhook_secret` | +|----------|-------------|---------| +| `GITHUB_WEBHOOK_SECRET` | Secret for verifying GitHub webhook signatures (for Sponsors) | `your_webhook_secret` | | `TELEGRAM_TOKEN` | Telegram Bot API token | `1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZ` | | `TELEGRAM_CHAT_ID` | Telegram chat ID to send notifications to | `123456789` | | `WEBHOOK_HOST` | Host to bind the webhook server to (optional) | `0.0.0.0` | | `WEBHOOK_PORT` | Port to bind the webhook server to (optional) | `5000` | -### GitHub Webhook Setup +**Binance Alerts (Optional):** +| Variable | Description | +|----------|-------------| +| `BINANCE_API_KEY` | Your Binance API Key | +| `BINANCE_API_SECRET` | Your Binance API Secret | +| `BINANCE_POLL_INTERVAL` | Interval in seconds to poll Binance (default: 300) | -1. Go to your GitHub repository or organization settings -2. Navigate to "Webhooks" and click "Add webhook" -3. For the Payload URL, enter your server URL (e.g., `https://your-server.com/webhook/github`) -4. Set Content type to `application/json` -5. Generate a secure random string to use as your webhook secret: - ```bash - openssl rand -hex 20 - ``` -6. Enter this secret in the "Secret" field and in your `.env` file -7. Under "Which events would you like to trigger this webhook?", select "Let me select individual events" -8. Check only the "Sponsorships" option -9. Ensure "Active" is checked and click "Add webhook" +**IMAP Email Alerts (Optional - for UPI/HDFC):** +| Variable | Description | +|----------|-------------| +| `IMAP_HOST` | IMAP server hostname | +| `IMAP_PORT` | IMAP server port (default: 993 for SSL) | +| `IMAP_USER` | IMAP account username | +| `IMAP_PASSWORD` | IMAP account password | +| `IMAP_MAILBOX` | Mailbox to check (default: INBOX) | +| `IMAP_POLL_INTERVAL` | Interval in seconds to poll IMAP (default: 600) | +| `UPI_EMAIL_SENDER_FILTER` | Optional: Email address or keyword to filter UPI emails | +| `HDFC_EMAIL_SENDER_FILTER` | Optional: Email address or keyword to filter HDFC emails | + +### GitHub Webhook Setup (for GitHub Sponsors) + +1. Go to your GitHub repository or organization settings. +2. Navigate to "Webhooks" and click "Add webhook". +3. For the Payload URL, enter your server URL (e.g., `https://your-server.com/webhook/github`). +4. Set Content type to `application/json`. +5. Generate a secure random string for your webhook secret (e.g., `openssl rand -hex 20`). +6. Enter this secret in the "Secret" field on GitHub and in your `.env` file (`GITHUB_WEBHOOK_SECRET`). +7. Under "Which events would you like to trigger this webhook?", select "Let me select individual events". +8. Check only the "Sponsorships" option. +9. Ensure "Active" is checked and click "Add webhook". + +### Binance API Setup (for Binance Alerts) + +1. Log in to your Binance account. +2. Navigate to API Management (usually under your profile icon). +3. Create a new API key. +4. **Important Security Note**: + - Grant only necessary permissions (e.g., "Enable Reading" for fetching transaction history). **Do NOT enable trading or withdrawal permissions unless absolutely necessary and you understand the risks.** + - Consider restricting API key access to trusted IP addresses if possible. +5. Copy the API Key and Secret Key to your `.env` file (`BINANCE_API_KEY`, `BINANCE_API_SECRET`). + +### IMAP Email Setup (for UPI/HDFC Alerts) + +1. Ensure IMAP access is enabled for the email account you want to use. +2. Gather your IMAP server details: + - IMAP Host (e.g., `imap.gmail.com`, `outlook.office365.com`) + - IMAP Port (usually 993 for SSL/TLS, or 143 for non-SSL) + - Your email username and password (or an app-specific password if your provider requires it, like Gmail with 2FA). +3. Enter these details into your `.env` file (`IMAP_HOST`, `IMAP_PORT`, `IMAP_USER`, `IMAP_PASSWORD`). +4. Specify the `IMAP_MAILBOX` (e.g., `INBOX`, or a specific folder where payment emails arrive). +5. Optionally, set `UPI_EMAIL_SENDER_FILTER` and `HDFC_EMAIL_SENDER_FILTER` to help the bot identify relevant emails. These can be sender email addresses (e.g., `alerts@hdfcbank.com`) or keywords expected in the subject/body. + +**Note on Email Parsing**: The accuracy of UPI/HDFC alerts depends heavily on the consistency of email formats. The parsing logic in `payment_sources/imap_alerts.py` may need to be customized based on the specific emails you receive. ### Telegram Bot Setup -1. Open Telegram and search for [@BotFather](https://t.me/botfather) -2. Send the command `/newbot` and follow the instructions -3. BotFather will provide you with a token (copy this to your `.env` file) -4. Start a chat with your new bot by clicking the link provided by BotFather -5. To get your chat ID, start a chat with [@userinfobot](https://t.me/userinfobot) -6. The bot will reply with your account information, including your Chat ID -7. Copy this Chat ID to your `.env` file +1. Open Telegram and search for [@BotFather](https://t.me/botfather). +2. Send the command `/newbot` and follow the instructions. +3. BotFather will provide you with a token (copy this to `TELEGRAM_TOKEN` in your `.env` file). +4. Start a chat with your new bot by clicking the link provided by BotFather. +5. To get your chat ID, start a chat with [@userinfobot](https://t.me/userinfobot). +6. The bot will reply with your account information, including your Chat ID. +7. Copy this Chat ID to `TELEGRAM_CHAT_ID` in your `.env` file. ## 🎮 Usage @@ -155,19 +218,20 @@ The bot requires the following environment variables to be set in your `.env` fi Once configured, the bot will: -1. Start a webhook server listening for GitHub events -2. Initialize the Telegram bot -3. Send a startup message to your Telegram chat -4. Process incoming webhook events and send notifications +1. Start a webhook server listening for GitHub Sponsors events (if configured). +2. Initialize the Telegram bot. +3. Start polling threads for Binance and/or IMAP email alerts (if configured and enabled). +4. Send a startup message to your Telegram chat indicating active services. +5. Process incoming events/data and send notifications. The bot logs its activity to both the console and a log file (`github_sponsors_bot.log`). ### Testing the Webhook -You can test the webhook integration without setting up a real GitHub webhook by using the included test script: +You can test the GitHub Sponsors webhook integration without setting up a real GitHub webhook by using the included test script: ```bash -python test_webhook.py +python3 test_webhook.py # Or use 'python' ``` This will send a simulated GitHub Sponsors webhook event to your local server. If everything is set up correctly, you should receive a notification in your Telegram chat. @@ -187,141 +251,65 @@ Then update your GitHub webhook URL with the ngrok URL (e.g., `https://a1b2c3d4. For local development or personal use, you can run the bot directly on your machine: ```bash -python github_sponsors_bot.py +python3 github_sponsors_bot.py # Or use 'python' ``` -To keep the bot running after you close your terminal, you can use tools like: - -- `nohup` on Linux/macOS: - ```bash - nohup python github_sponsors_bot.py & - ``` -- `screen` or `tmux` for terminal sessions: - ```bash - screen -S sponsors-bot - python github_sponsors_bot.py - # Press Ctrl+A, D to detach - ``` -- Windows Task Scheduler for Windows systems +To keep the bot running after you close your terminal, use tools like `nohup` (Linux/macOS), `screen`/`tmux`, or Windows Task Scheduler. ### Cloud Deployment -For production use, we recommend deploying to a cloud provider: - -#### Heroku - -1. Install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) -2. Login and create a new app: - ```bash - heroku login - heroku create your-app-name - ``` -3. Set environment variables: - ```bash - heroku config:set GITHUB_WEBHOOK_SECRET=your_secret - heroku config:set TELEGRAM_TOKEN=your_telegram_token - heroku config:set TELEGRAM_CHAT_ID=your_chat_id - ``` -4. Deploy the app: - ```bash - git push heroku main - ``` -5. Update your GitHub webhook URL to `https://your-app-name.herokuapp.com/webhook/github` - -#### AWS - -1. Create an EC2 instance -2. Install Docker on the instance -3. Clone the repository and build the Docker image -4. Run the container with your environment variables -5. Set up a load balancer or Elastic IP for a stable endpoint -6. Update your GitHub webhook URL with your instance's public address - -#### Digital Ocean - -1. Create a Droplet -2. Install Docker on the Droplet -3. Clone the repository and build the Docker image -4. Run the container with your environment variables -5. Set up a Floating IP for a stable endpoint -6. Update your GitHub webhook URL with your Droplet's public address +For production use, deploying to a cloud provider is recommended. The Docker setup facilitates this. Examples include Heroku, AWS EC2, Digital Ocean Droplets. Ensure your environment variables are securely configured on the cloud platform. ## 🏗️ Architecture -The bot is designed with a simple, single-file architecture for ease of understanding and maintenance. For more details on the architecture, see [ARCHITECTURE.md](ARCHITECTURE.md). +The bot is designed with a modular architecture: +- **Main Application (`github_sponsors_bot.py`)**: Handles core logic, Flask web server for GitHub webhooks, Telegram bot initialization, and orchestration of polling threads. +- **Payment Source Modules (`payment_sources/`)**: + - `binance_alerts.py`: Connects to Binance API, fetches payment data. + - `imap_alerts.py`: Connects to IMAP server, fetches and parses emails for UPI/HDFC. +- **Configuration**: Managed via environment variables (`.env` file). -Key components: - -1. **Flask Web Server**: Handles incoming webhook requests -2. **Webhook Handler**: Verifies and processes GitHub webhook events -3. **Telegram Bot**: Sends notifications to your Telegram chat +For more details, see [ARCHITECTURE.md](ARCHITECTURE.md). ## 🔍 Troubleshooting ### Common Issues -#### Webhook Not Receiving Events - -- **Problem**: GitHub webhook events aren't being received by your server. -- **Solutions**: - - Verify your server is publicly accessible - - Check that the webhook URL in GitHub settings is correct - - Ensure your server is running and listening on the correct port - - Check firewall settings to allow incoming connections - - Look at GitHub webhook delivery logs for error details - -#### Invalid Signature Errors - -- **Problem**: Webhook requests are being rejected due to invalid signatures. -- **Solutions**: - - Verify the webhook secret in your `.env` file matches the one in GitHub settings - - Ensure the webhook payload is not being modified in transit (use HTTPS) - - Check that the content type is set to `application/json` in GitHub webhook settings - -#### Telegram Bot Not Sending Messages - -- **Problem**: Notifications aren't being sent to Telegram. -- **Solutions**: - - Confirm your bot token is correct - - Ensure you've started a conversation with your bot - - Verify your chat ID is correct - - Check if the bot has been blocked or deleted - - Look at the bot logs for error messages - -#### Docker Container Issues - -- **Problem**: Docker container won't start or crashes. -- **Solutions**: - - Check Docker logs: `docker logs sponsors-bot` - - Verify environment variables are set correctly - - Ensure the required ports are available - - Check for permission issues +- **Webhook Not Receiving Events (GitHub)**: + - Verify server accessibility, webhook URL, server status, firewall. + - Check GitHub webhook delivery logs. +- **Invalid Signature Errors (GitHub)**: + - Match `GITHUB_WEBHOOK_SECRET` between GitHub and `.env`. + - Ensure `application/json` content type. +- **Telegram Bot Not Sending Messages**: + - Correct `TELEGRAM_TOKEN` and `TELEGRAM_CHAT_ID`. + - Ensure you've started a chat with the bot. +- **Binance/IMAP Alerts Not Working**: + - Double-check API keys/credentials in `.env`. + - Verify polling intervals and necessary permissions (Binance API, IMAP access). + - Check logs for specific error messages from these modules. + - For IMAP, ensure email filters (`UPI_EMAIL_SENDER_FILTER`, `HDFC_EMAIL_SENDER_FILTER`) are correctly set if used, and that the parsing logic in `imap_alerts.py` matches your email formats. +- **Docker Container Issues**: + - Check Docker logs: `docker logs payment-alert-bot`. + - Verify environment variables and port availability. ### Debugging -To enable more detailed logging, you can modify the logging level in `github_sponsors_bot.py`: - +To enable more detailed logging, modify the logging level in `github_sponsors_bot.py`: ```python logging.basicConfig( level=logging.DEBUG, # Change from INFO to DEBUG - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.StreamHandler(), - logging.FileHandler('github_sponsors_bot.log') - ] + # ... rest of the config ) ``` ## ⚡ Performance Optimization -For optimal performance: - -1. **Use HTTPS**: Always use HTTPS for your webhook endpoint to ensure secure communication. -2. **Minimize Response Time**: The webhook handler should process events quickly to avoid timeouts. -3. **Use a Production WSGI Server**: For production deployments, use Gunicorn (included in the Docker setup) or uWSGI instead of Flask's development server. -4. **Monitor Resource Usage**: Keep an eye on CPU and memory usage, especially for high-traffic repositories. -5. **Implement Rate Limiting**: If you expect a high volume of sponsorships, consider implementing rate limiting for Telegram notifications. -6. **Use a Reverse Proxy**: For production deployments, use Nginx or Apache as a reverse proxy in front of the application. +- **Use HTTPS**: For GitHub webhook endpoint. +- **Efficient Polling**: Set reasonable `BINANCE_POLL_INTERVAL` and `IMAP_POLL_INTERVAL` to avoid excessive API/server load. +- **Production WSGI Server**: For production, use Gunicorn (included in Docker) or uWSGI. +- **Monitor Resources**: Keep an eye on CPU/memory. +- **Reverse Proxy**: Use Nginx or Apache for production deployments. ## 🤝 Contributing @@ -329,4 +317,4 @@ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for gui ## 📄 License -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. \ No newline at end of file +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/github_sponsors_bot.py b/github_sponsors_bot.py index 31b5bcc..b205fb4 100644 --- a/github_sponsors_bot.py +++ b/github_sponsors_bot.py @@ -1,8 +1,11 @@ #!/usr/bin/env python3 """ -GitHub Sponsors Webhook Bot +GitHub Sponsors and Multi-Source Payment Alert Bot -This bot receives GitHub Sponsors webhook events and sends notifications to Telegram. +This bot: +- Receives GitHub Sponsors webhook events and sends notifications to Telegram. +- Polls Binance for new cryptocurrency deposits and P2P payments. +- Polls an IMAP email account for UPI and HDFC Bank payment notifications. It provides real-time payment notifications with complete transaction details. Usage: @@ -14,6 +17,21 @@ Environment variables required: TELEGRAM_CHAT_ID - Telegram chat ID to send notifications to WEBHOOK_HOST - Host to bind the webhook server to (default: 0.0.0.0) WEBHOOK_PORT - Port to bind the webhook server to (default: 5000) + + # Binance Alerts (Optional) + BINANCE_API_KEY - Binance API Key + BINANCE_API_SECRET - Binance API Secret + BINANCE_POLL_INTERVAL - Interval in seconds to poll Binance (default: 300) + + # IMAP Email Alerts (Optional) + IMAP_HOST - IMAP server host + IMAP_PORT - IMAP server port (default: 993 for SSL) + IMAP_USER - IMAP account username + IMAP_PASSWORD - IMAP account password + IMAP_MAILBOX - Mailbox to check (default: INBOX) + IMAP_POLL_INTERVAL - Interval in seconds to poll IMAP server (default: 600) + UPI_EMAIL_SENDER_FILTER - Optional: Email address or domain to filter UPI emails + HDFC_EMAIL_SENDER_FILTER - Optional: Email address or domain to filter HDFC emails """ import os @@ -22,6 +40,8 @@ import logging import hmac import hashlib import sys +import time +import threading from datetime import datetime import telegram @@ -29,6 +49,9 @@ from telegram.ext import Updater, CommandHandler from flask import Flask, request, jsonify from dotenv import load_dotenv +from payment_sources.binance_alerts import BinanceAlerts +from payment_sources.imap_alerts import ImapAlerts + # Load environment variables load_dotenv() @@ -49,10 +72,16 @@ TELEGRAM_TOKEN = os.getenv('TELEGRAM_TOKEN') TELEGRAM_CHAT_ID = os.getenv('TELEGRAM_CHAT_ID') WEBHOOK_HOST = os.getenv('WEBHOOK_HOST', '0.0.0.0') WEBHOOK_PORT = int(os.getenv('WEBHOOK_PORT', 5000)) +BINANCE_POLL_INTERVAL = int(os.getenv('BINANCE_POLL_INTERVAL', 300)) +IMAP_POLL_INTERVAL = int(os.getenv('IMAP_POLL_INTERVAL', 600)) # Initialize Flask app app = Flask(__name__) +# Global Alerter Instances +binance_alerter = None +imap_alerter = None + class TelegramBot: """Class to handle Telegram bot functionality""" @@ -164,10 +193,7 @@ telegram_bot = TelegramBot(TELEGRAM_TOKEN, TELEGRAM_CHAT_ID) def verify_github_signature(request_data, signature_header): """Verify that the webhook request is from GitHub using the webhook secret""" - if not GITHUB_WEBHOOK_SECRET: - logger.warning("GITHUB_WEBHOOK_SECRET not configured, skipping signature verification") - return True - + # GITHUB_WEBHOOK_SECRET is guaranteed to be present due to checks in main() if not signature_header: logger.error("No X-Hub-Signature-256 header in request") return False @@ -286,8 +312,39 @@ def run_webhook_server(): app.run(host=WEBHOOK_HOST, port=WEBHOOK_PORT) +# --- Polling functions for payment sources --- +def poll_binance_payments(): + """Periodically polls Binance for new payments.""" + global binance_alerter + if not binance_alerter or not binance_alerter.enabled: + logger.info("Binance alerter not initialized or disabled. Binance polling thread will not run.") + return + logger.info("Starting Binance payment polling thread.") + while True: + try: + binance_alerter.check_for_new_payments() + except Exception as e: + logger.error(f"Error in Binance polling loop: {e}") + time.sleep(BINANCE_POLL_INTERVAL) + +def poll_imap_emails(): + """Periodically polls IMAP server for new payment emails.""" + global imap_alerter + if not imap_alerter or not imap_alerter.enabled: + logger.info("IMAP alerter not initialized or disabled. IMAP polling thread will not run.") + return + logger.info("Starting IMAP email polling thread.") + while True: + try: + imap_alerter.check_for_new_emails() + except Exception as e: + logger.error(f"Error in IMAP polling loop: {e}") + time.sleep(IMAP_POLL_INTERVAL) + def main(): """Main function to run the bot""" + global binance_alerter, imap_alerter + # Validate required configuration if not GITHUB_WEBHOOK_SECRET: logger.error("GITHUB_WEBHOOK_SECRET not configured") @@ -310,12 +367,30 @@ def main(): sys.exit(1) telegram_bot.start_polling() + + # Initialize payment alerters + binance_alerter = BinanceAlerts(telegram_bot) + imap_alerter = ImapAlerts(telegram_bot) + + # Start polling threads + if binance_alerter.enabled: + binance_thread = threading.Thread(target=poll_binance_payments, daemon=True) + binance_thread.start() + + if imap_alerter.enabled: + imap_thread = threading.Thread(target=poll_imap_emails, daemon=True) + imap_thread.start() # Send startup message startup_message = ( - "🚀 *GitHub Sponsors Webhook Bot Started*\n\n" - "Ready to receive GitHub Sponsors webhook events and send notifications." + "🚀 *Multi-Source Payment Alert Bot Started*\n\n" + "Listening for GitHub Sponsors webhooks.\n" ) + if binance_alerter and binance_alerter.enabled: + startup_message += "Polling Binance for payments.\n" + if imap_alerter and imap_alerter.enabled: + startup_message += "Polling IMAP for email notifications.\n" + telegram_bot.send_message(startup_message) try: @@ -332,4 +407,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/payment_sources/__init__.py b/payment_sources/__init__.py new file mode 100644 index 0000000..b29695d --- /dev/null +++ b/payment_sources/__init__.py @@ -0,0 +1 @@ +# This file makes the payment_sources directory a Python package. diff --git a/payment_sources/binance_alerts.py b/payment_sources/binance_alerts.py new file mode 100644 index 0000000..e0ad99b --- /dev/null +++ b/payment_sources/binance_alerts.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +""" +Handles Binance payment alerts. + +This module will connect to the Binance API to fetch: +- New cryptocurrency deposits. +- Completed P2P payment receipts. +""" + +import os +import logging +# from binance.client import Client # To be added when implementing + +logger = logging.getLogger("GitHubSponsorsBot.BinanceAlerts") + +# Environment variables for Binance API (ensure these are set) +BINANCE_API_KEY = os.getenv('BINANCE_API_KEY') +BINANCE_API_SECRET = os.getenv('BINANCE_API_SECRET') + +class BinanceAlerts: + def __init__(self, telegram_bot): + self.telegram_bot = telegram_bot + # self.client = Client(BINANCE_API_KEY, BINANCE_API_SECRET) # Uncomment when ready + if not BINANCE_API_KEY or not BINANCE_API_SECRET: + logger.error("Binance API Key or Secret not configured. Binance alerts will be disabled.") + self.enabled = False + else: + self.enabled = True + # Initialize API client here + pass + + def check_for_new_payments(self): + """ + Checks for new deposits and P2P payments and sends alerts. + """ + if not self.enabled: + return + + logger.info("Checking for new Binance payments...") + # TODO: Implement logic to fetch new crypto deposits + # Example: + # deposits = self.client.get_deposit_history() + # for deposit in deposits: + # if self.is_new_deposit(deposit): # Implement is_new_deposit to avoid duplicates + # message = self.format_deposit_message(deposit) + # self.telegram_bot.send_message(message) + # self.mark_deposit_as_processed(deposit) # Mark to avoid re-alerting + + # TODO: Implement logic to fetch completed P2P payments + # Example: + # p2p_orders = self.client.get_c2c_trade_history(tradeType='BUY') # or relevant endpoint + # for order in p2p_orders: + # if order['orderStatus'] == 'COMPLETED' and self.is_new_p2p_payment(order): + # message = self.format_p2p_message(order) + # self.telegram_bot.send_message(message) + # self.mark_p2p_as_processed(order) + logger.info("Finished checking Binance payments.") + + def format_deposit_message(self, deposit_data): + """ + Formats a cryptocurrency deposit alert message. + """ + # Example structure, adjust based on actual API response + # amount = deposit_data.get('amount') + # currency = deposit_data.get('coin') + # tx_id = deposit_data.get('txId') + # timestamp = deposit_data.get('insertTime') # Convert to readable format + # formatted_time = datetime.fromtimestamp(timestamp/1000).strftime('%Y-%m-%d %H:%M:%S') if timestamp else 'N/A' + # + # message = ( + # f"💰 *New Binance Deposit Received*\n\n" + # f"*Amount:* {amount} {currency}\n" + # f"*Transaction ID:* `{tx_id}`\n" + # f"*Timestamp:* {formatted_time}\n" + # ) + # return message + return "Placeholder Binance deposit message" # Replace with actual formatting + + def format_p2p_message(self, p2p_data): + """ + Formats a P2P payment receipt alert message. + """ + # Example structure, adjust based on actual API response + # order_number = p2p_data.get('orderNumber') + # amount = p2p_data.get('totalPrice') + # currency = p2p_data.get('fiatUnit') + # crypto_amount = p2p_data.get('amount') + # crypto_currency = p2p_data.get('asset') + # timestamp = p2p_data.get('createTime') # Convert to readable format + # formatted_time = datetime.fromtimestamp(timestamp/1000).strftime('%Y-%m-%d %H:%M:%S') if timestamp else 'N/A' + # + # message = ( + # f"🤝 *Binance P2P Payment Completed*\n\n" + # f"*Order Number:* `{order_number}`\n" + # f"*Fiat Amount:* {amount} {currency}\n" + # f"*Crypto Amount:* {crypto_amount} {crypto_currency}\n" + # f"*Timestamp:* {formatted_time}\n" + # ) + # return message + return "Placeholder Binance P2P message" # Replace with actual formatting + + # Helper methods to track processed transactions (to avoid duplicate alerts) + # These could use a simple in-memory set for recent IDs, or a small DB/file for persistence + def is_new_deposit(self, deposit_data): + # TODO: Implement logic to check if this deposit has been alerted already + return True + + def mark_deposit_as_processed(self, deposit_data): + # TODO: Implement logic to mark this deposit as processed + pass + + def is_new_p2p_payment(self, p2p_data): + # TODO: Implement logic to check if this P2P payment has been alerted already + return True + + def mark_p2p_as_processed(self, p2p_data): + # TODO: Implement logic to mark this P2P payment as processed + pass + +if __name__ == '__main__': + # This section is for testing the module independently + # You'll need to mock telegram_bot or provide a dummy one + class MockTelegramBot: + def send_message(self, message): + print(f"MockTelegramBot sending: {message}") + + # Ensure environment variables are set for testing + # load_dotenv() # If you have a .env file for testing + # BINANCE_API_KEY = os.getenv('BINANCE_API_KEY_TEST') + # BINANCE_API_SECRET = os.getenv('BINANCE_API_SECRET_TEST') + + if BINANCE_API_KEY and BINANCE_API_SECRET: + logger.info("Running BinanceAlerts standalone test...") + mock_bot = MockTelegramBot() + binance_alerter = BinanceAlerts(mock_bot) + if binance_alerter.enabled: + binance_alerter.check_for_new_payments() + else: + logger.warning("Binance alerts are disabled due to missing API credentials.") + else: + logger.warning("Skipping BinanceAlerts standalone test: API credentials not found.") diff --git a/payment_sources/imap_alerts.py b/payment_sources/imap_alerts.py new file mode 100644 index 0000000..9bcbc93 --- /dev/null +++ b/payment_sources/imap_alerts.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 +""" +Handles payment alerts from emails via IMAP. + +This module will connect to an IMAP server to: +- Fetch new emails from a specified account. +- Parse emails to identify UPI and HDFC Bank payment notifications. +- Extract payment details (amount, sender/description, transaction ID, timestamp). +""" + +import os +import logging +import imaplib +import email +from email.header import decode_header +from datetime import datetime + +logger = logging.getLogger("GitHubSponsorsBot.ImapAlerts") + +# Environment variables for IMAP (ensure these are set) +IMAP_HOST = os.getenv('IMAP_HOST') +IMAP_PORT = os.getenv('IMAP_PORT', 993) # Default to 993 for IMAP SSL +IMAP_USER = os.getenv('IMAP_USER') +IMAP_PASSWORD = os.getenv('IMAP_PASSWORD') +IMAP_MAILBOX = os.getenv('IMAP_MAILBOX', 'INBOX') +# Optional: Define specific sender emails or subjects to filter for UPI/HDFC +UPI_EMAIL_SENDER_FILTER = os.getenv('UPI_EMAIL_SENDER_FILTER') +HDFC_EMAIL_SENDER_FILTER = os.getenv('HDFC_EMAIL_SENDER_FILTER') + +class ImapAlerts: + def __init__(self, telegram_bot): + self.telegram_bot = telegram_bot + self.enabled = False + if not all([IMAP_HOST, IMAP_USER, IMAP_PASSWORD]): + logger.error("IMAP configuration (HOST, USER, PASSWORD) incomplete. IMAP alerts will be disabled.") + else: + self.enabled = True + logger.info(f"IMAP Alerts initialized for user {IMAP_USER} on host {IMAP_HOST}") + + def _connect(self): + """Connects to the IMAP server.""" + try: + if str(IMAP_PORT) == '993': # Common port for IMAP SSL + mail = imaplib.IMAP4_SSL(IMAP_HOST, int(IMAP_PORT)) + else: + mail = imaplib.IMAP4(IMAP_HOST, int(IMAP_PORT)) + mail.login(IMAP_USER, IMAP_PASSWORD) + mail.select(IMAP_MAILBOX) + logger.info(f"Successfully connected to IMAP server and selected mailbox '{IMAP_MAILBOX}'.") + return mail + except Exception as e: + logger.error(f"Failed to connect to IMAP server: {e}") + return None + + def check_for_new_emails(self): + """ + Checks for new emails, parses them, and sends alerts. + """ + if not self.enabled: + return + + logger.info("Checking for new emails via IMAP...") + mail = self._connect() + if not mail: + return + + try: + # Search for unseen emails. Add more criteria if needed (e.g., SENDER, SUBJECT) + status, messages = mail.search(None, 'UNSEEN') + if status != 'OK': + logger.error("Failed to search for emails.") + return + + email_ids = messages[0].split() + logger.info(f"Found {len(email_ids)} unseen emails.") + + for email_id in email_ids: + status, msg_data = mail.fetch(email_id, '(RFC822)') + if status == 'OK': + for response_part in msg_data: + if isinstance(response_part, tuple): + msg = email.message_from_bytes(response_part[1]) + + # Decode email subject + subject, encoding = decode_header(msg["Subject"])[0] + if isinstance(subject, bytes): + subject = subject.decode(encoding if encoding else "utf-8") + + # Decode sender + from_ = msg.get("From") + logger.info(f"Processing email from: {from_}, subject: {subject}") + + # Get email body + body = "" + if msg.is_multipart(): + for part in msg.walk(): + content_type = part.get_content_type() + content_disposition = str(part.get("Content-Disposition")) + try: + if content_type == "text/plain" and "attachment" not in content_disposition: + body = part.get_payload(decode=True).decode() + break + except Exception as e: + logger.warning(f"Could not decode part of email: {e}") + else: + try: + body = msg.get_payload(decode=True).decode() + except Exception as e: + logger.warning(f"Could not decode email body: {e}") + + # TODO: Implement parsing logic for UPI and HDFC notifications + # This will be complex and require specific rules based on email formats. + payment_details = self.parse_payment_email(subject, from_, body) + + if payment_details: + alert_message = self.format_email_payment_message(payment_details) + self.telegram_bot.send_message(alert_message) + logger.info(f"Sent alert for payment: {payment_details.get('type')}") + # Optionally, mark email as read or move it + # mail.store(email_id, '+FLAGS', '\\Seen') + else: + logger.info(f"Email from {from_} with subject '{subject}' did not match payment patterns.") + else: + logger.error(f"Failed to fetch email ID {email_id}") + except Exception as e: + logger.error(f"Error during email processing: {e}") + finally: + if mail: + mail.close() + mail.logout() + logger.info("IMAP connection closed.") + logger.info("Finished checking IMAP emails.") + + def parse_payment_email(self, subject, from_address, body): + """ + Parses email content to extract payment details. + This needs to be highly customized based on the exact format of UPI/HDFC emails. + Returns a dictionary with extracted details or None. + """ + # Placeholder - very basic example + # You'll need robust regex or string searching here. + + # Example for HDFC Credit Card Transaction (highly hypothetical) + if HDFC_EMAIL_SENDER_FILTER and HDFC_EMAIL_SENDER_FILTER.lower() in from_address.lower(): + if "transaction alert" in subject.lower() and "hdfc bank credit card" in body.lower(): + # Regex to find amount, merchant, etc. + # amount_match = re.search(r"Rs\.([\d,]+\.\d{2})", body) + # merchant_match = re.search(r"at ([\w\s]+) on", body) + # if amount_match and merchant_match: + # return { + # "type": "HDFC Credit Card", + # "amount": amount_match.group(1), + # "currency": "INR", + # "description": merchant_match.group(1).strip(), + # "transaction_id": "N/A (extract if available)", + # "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S') # Extract from email if possible + # } + logger.info("Potential HDFC email found, parsing logic to be implemented.") + pass # Added pass to fix indentation + + + # Example for UPI Transaction (highly hypothetical) + if UPI_EMAIL_SENDER_FILTER and UPI_EMAIL_SENDER_FILTER.lower() in from_address.lower(): + if "payment received" in subject.lower() and "upi" in body.lower(): + # Regex to find amount, sender, UPI ID etc. + # amount_match = re.search(r"amount of INR ([\d,]+\.\d{2})", body) + # sender_match = re.search(r"from ([\w\s@\.]+)", body) # Could be name or VPA + # if amount_match and sender_match: + # return { + # "type": "UPI", + # "amount": amount_match.group(1), + # "currency": "INR", + # "description": f"Payment from {sender_match.group(1).strip()}", + # "transaction_id": "N/A (extract if available)", + # "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S') # Extract from email if possible + # } + logger.info("Potential UPI email found, parsing logic to be implemented.") + pass # Added pass to fix indentation + + return None # No relevant payment found or parsing failed + + def format_email_payment_message(self, details): + """ + Formats an alert message for a payment extracted from an email. + """ + payment_type = details.get("type", "Unknown Payment") + amount = details.get("amount", "N/A") + currency = details.get("currency", "") + description = details.get("description", "N/A") + tx_id = details.get("transaction_id", "N/A") + timestamp = details.get("timestamp", "N/A") + + message = ( + f"📧 *New {payment_type} Alert (from Email)*\n\n" + f"*Amount:* {amount} {currency}\n" + f"*Details:* {description}\n" + f"*Transaction ID:* `{tx_id}`\n" + f"*Timestamp:* {timestamp}\n" + ) + return message + +if __name__ == '__main__': + # This section is for testing the module independently + class MockTelegramBot: + def send_message(self, message): + print(f"MockTelegramBot sending: {message}") + + # Ensure environment variables are set for testing + # from dotenv import load_dotenv + # load_dotenv() # If you have a .env file for testing + # IMAP_HOST = os.getenv('IMAP_HOST_TEST') + # IMAP_USER = os.getenv('IMAP_USER_TEST') + # IMAP_PASSWORD = os.getenv('IMAP_PASSWORD_TEST') + + if IMAP_HOST and IMAP_USER and IMAP_PASSWORD: + logger.info("Running ImapAlerts standalone test...") + mock_bot = MockTelegramBot() + imap_alerter = ImapAlerts(mock_bot) + if imap_alerter.enabled: + imap_alerter.check_for_new_emails() + else: + logger.warning("IMAP alerts are disabled due to missing credentials.") + else: + logger.warning("Skipping ImapAlerts standalone test: IMAP credentials not found.") diff --git a/requirements.txt b/requirements.txt index 458d37e..789dc38 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,5 @@ requests>=2.25.1 python-dotenv>=0.19.0 pyyaml>=6.0 flask>=2.0.0 -gunicorn>=20.1.0 \ No newline at end of file +gunicorn>=20.1.0 +python-binance>=1.0.19 # For Binance API interaction