{"id":30666268,"url":"https://github.com/btholt/discord-unifi","last_synced_at":"2025-08-31T21:49:08.092Z","repository":{"id":306954279,"uuid":"1026401037","full_name":"btholt/discord-unifi","owner":"btholt","description":"Docker container to accept local webhooks from Unifi Protect and send them to Discord","archived":false,"fork":false,"pushed_at":"2025-07-28T21:18:30.000Z","size":62,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-28T15:54:33.718Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/btholt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-25T20:28:41.000Z","updated_at":"2025-07-28T21:18:34.000Z","dependencies_parsed_at":"2025-07-28T17:37:35.945Z","dependency_job_id":"ca0558a4-baa3-4dc5-9188-696e8b49631c","html_url":"https://github.com/btholt/discord-unifi","commit_stats":null,"previous_names":["btholt/discord-unifi"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/btholt/discord-unifi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btholt%2Fdiscord-unifi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btholt%2Fdiscord-unifi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btholt%2Fdiscord-unifi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btholt%2Fdiscord-unifi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/btholt","download_url":"https://codeload.github.com/btholt/discord-unifi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/btholt%2Fdiscord-unifi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273046451,"owners_count":25036179,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-31T02:00:09.071Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-31T21:49:07.407Z","updated_at":"2025-08-31T21:49:08.069Z","avatar_url":"https://github.com/btholt.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unifi Protect to Discord Webhook Bridge\n\nA lightweight Node.js server that receives webhook posts from Unifi Protect Alarm Manager and forwards them to a Discord webhook. The entire application is containerized using Docker for easy deployment.\n\n## Features\n\n- 🚨 **Real-time Alerts**: Receive and forward Unifi Protect events to Discord\n- 🔒 **Security**: Rate limiting, request validation, and data sanitization\n- 📊 **Structured Logging**: Comprehensive logging with request tracing\n- 🐳 **Docker Ready**: Complete containerization with health checks\n- ⚡ **Lightweight**: Optimized for minimal resource usage\n- 🔧 **Configurable**: Environment-based configuration\n\n## Quick Start\n\n### Option 1: Using Published Docker Image (Recommended)\n\nThe latest Docker image is automatically published to GitHub Container Registry on each release.\n\n```bash\n# Pull the latest image\ndocker pull ghcr.io/btholt/discord-unifi:latest\n\n# Run with environment variables\ndocker run -d \\\n  --name unifi-discord-bridge \\\n  -p 3000:3000 \\\n  -e DISCORD_WEBHOOK_URL=\"https://discord.com/api/webhooks/YOUR_WEBHOOK_URL_HERE\" \\\n  ghcr.io/btholt/discord-unifi:latest\n```\n\n### Option 2: Local Development\n\n#### Prerequisites\n\n- Docker and Docker Compose\n- Discord webhook URL\n- Unifi Protect system with webhook capability\n\n#### 1. Clone and Setup\n\n```bash\ngit clone \u003crepository-url\u003e\ncd unifi-discord-bridge\ncp env.example .env\n```\n\n#### 2. Configure Environment\n\nEdit `.env` file with your Discord webhook URL:\n\n```bash\nDISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/YOUR_WEBHOOK_URL_HERE\n```\n\n#### 3. Run with Docker Compose\n\n```bash\ndocker-compose up -d\n```\n\nThe service will be available at `http://localhost:3000`\n\n## Configuration\n\n### Environment Variables\n\n| Variable              | Default          | Description                                  |\n| --------------------- | ---------------- | -------------------------------------------- |\n| `PORT`                | `3000`           | Server port                                  |\n| `DISCORD_WEBHOOK_URL` | **Required**     | Discord webhook URL                          |\n| `WEBHOOK_PATH`        | `/webhook/unifi` | Endpoint path for Unifi webhooks             |\n| `LOG_LEVEL`           | `info`           | Logging level (error, warn, info, debug)     |\n| `WEBHOOK_SECRET`      | -                | Optional secret for webhook validation       |\n| `RATE_LIMIT_WINDOW`   | `15`             | Rate limiting window in minutes              |\n| `RATE_LIMIT_MAX`      | `100`            | Max requests per window                      |\n| `PROTECT_API_KEY`     | -                | Unifi Protect API key for thumbnail fetching |\n| `PROTECT_HOST`        | `192.168.1.80`   | Unifi Protect host address                   |\n\n### Discord Webhook Setup\n\n1. Go to your Discord server settings\n2. Navigate to Integrations → Webhooks\n3. Create a new webhook\n4. Copy the webhook URL\n5. Set it as `DISCORD_WEBHOOK_URL` in your environment\n\n## API Endpoints\n\n### Webhook Endpoint\n\n- **POST** `/webhook/unifi` - Receive Unifi Protect webhooks\n- **GET** `/webhook/unifi/health` - Health check endpoint\n\n### Root Endpoint\n\n- **GET** `/` - Service information\n\n## Unifi Protect Webhook Format\n\nThe service expects JSON payloads from Unifi Protect with the following structure:\n\n```json\n{\n  \"alarm\": {\n    \"name\": \"Motion Detected\",\n    \"sources\": [],\n    \"conditions\": [\n      {\n        \"condition\": {\n          \"type\": \"is\",\n          \"source\": \"motion\"\n        }\n      }\n    ],\n    \"triggers\": [\n      {\n        \"key\": \"motion\",\n        \"device\": \"74ACB99F4E24\"\n      }\n    ]\n  },\n  \"timestamp\": 1722526793954\n}\n```\n\n### Supported Event Types\n\nThe service automatically detects event types from the `alarm.conditions[].condition.source` field:\n\n- `motion` - Motion detection events\n- `alert` - General alerts\n- `person` - Person detection\n- `vehicle` - Vehicle detection\n- `package` - Package detection\n- `face_known` - Known person face recognition\n- `face_unknown` - Unknown person face recognition\n- `unknown` - Fallback for unrecognized event types\n\n## Thumbnail Support\n\nWhen `PROTECT_API_KEY` is configured, the service automatically:\n\n1. **Fetches Animated Thumbnails**: Downloads GIF thumbnails from Unifi Protect\n2. **Uploads to Discord**: Attaches thumbnails to Discord messages\n3. **Fallback Gracefully**: Continues without thumbnails if API key is missing\n\n### Thumbnail Configuration\n\n```bash\n# Add to your .env file\nPROTECT_API_KEY=your_protect_api_key_here\nPROTECT_HOST=192.168.1.80  # Optional, defaults to 192.168.1.80\n```\n\n### Thumbnail URL Format\n\nThe service fetches thumbnails using:\n\n```\nhttp://{PROTECT_HOST}/proxy/protect/api/events/{eventId}/animated-thumbnail?keyFrameOnly=true\u0026speedup=10\n```\n\n## Discord Message Format\n\nEvents are transformed into rich Discord embeds with:\n\n- Event-specific emojis and colors\n- Camera information\n- Timestamps\n- Structured fields\n\nExample Discord message:\n\n```\n🚨 **Motion Detected**\n\nUnifi Protect Alert\nMotion detected on camera: Front Door\nCamera: Front Door | Event Type: Motion Detection\n```\n\n## Development\n\n### Local Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Start development server\nnpm run dev\n```\n\n### Building Docker Image\n\n```bash\n# Build image\ndocker build -t unifi-discord-bridge .\n\n# Run container\ndocker run -p 3000:3000 -e DISCORD_WEBHOOK_URL=your_url unifi-discord-bridge\n```\n\n## Logging\n\nThe application uses structured logging with Winston. Log levels:\n\n- `error` - Application errors\n- `warn` - Warning messages\n- `info` - General information\n- `debug` - Detailed debugging information\n\nEach request gets a unique request ID for tracing.\n\n## Security Features\n\n- **Rate Limiting**: Prevents abuse with configurable limits\n- **Request Validation**: Validates incoming webhook data\n- **Data Sanitization**: Removes sensitive information\n- **Helmet**: Security headers\n- **CORS**: Cross-origin resource sharing protection\n- **Non-root User**: Docker container runs as non-root user\n\n## Health Checks\n\nThe application includes health check endpoints for container orchestration:\n\n```bash\ncurl http://localhost:3000/webhook/unifi/health\n```\n\nResponse:\n\n```json\n{\n  \"status\": \"healthy\",\n  \"timestamp\": \"2025-01-15T10:30:00.000Z\",\n  \"service\": \"unifi-discord-bridge\",\n  \"version\": \"1.0.0\"\n}\n```\n\n## Troubleshooting\n\n### Common Issues\n\n1. **Discord webhook not working**\n\n   - Verify the webhook URL is correct\n   - Check Discord server permissions\n   - Ensure the webhook is not disabled\n\n2. **Rate limiting errors**\n\n   - Adjust `RATE_LIMIT_MAX` and `RATE_LIMIT_WINDOW` values\n   - Check if multiple instances are running\n\n3. **Container health check failing**\n   - Verify the service is running on the correct port\n   - Check container logs for errors\n\n### Logs\n\nView application logs:\n\n```bash\n# Docker Compose\ndocker-compose logs -f\n\n# Docker container\ndocker logs unifi-discord-bridge\n```\n\n## GitHub Actions \u0026 Releases\n\nThis project uses GitHub Actions for automated CI/CD:\n\n### 🚀 Automated Releases\n\nWhen you create a new release tag (e.g., `v1.0.1`), the workflow will:\n\n1. **Build Docker Image** - Multi-platform build (AMD64, ARM64)\n2. **Push to GHCR** - Publish to GitHub Container Registry\n3. **Create Release** - Generate release notes with usage instructions\n4. **Security Scan** - Run vulnerability scanning with Trivy\n\n### 📋 Creating a Release\n\n```bash\n# Create and push a new tag\ngit tag v1.0.1\ngit push origin v1.0.1\n```\n\nOr use the GitHub UI to create a release.\n\n### 🔄 CI/CD Pipeline\n\n- **Pull Requests**: Build and test on every PR\n- **Main Branch**: Build and push to GHCR on every push\n- **Security**: Automated vulnerability scanning\n- **Testing**: Docker image validation\n\n## Deployment\n\n### Production Deployment\n\n#### Option 1: Using Published Image (Recommended)\n\n```bash\n# Pull the latest release\ndocker pull ghcr.io/btholt/discord-unifi:latest\n\n# Run in production\ndocker run -d \\\n  --name unifi-discord-bridge \\\n  --restart unless-stopped \\\n  -p 3000:3000 \\\n  -e DISCORD_WEBHOOK_URL=\"your_discord_webhook_url\" \\\n  -e LOG_LEVEL=\"info\" \\\n  ghcr.io/btholt/discord-unifi:latest\n```\n\n#### Option 2: Local Build\n\n1. **Environment Setup**\n\n   ```bash\n   cp env.example .env\n   # Edit .env with production values\n   ```\n\n2. **Docker Compose**\n\n   ```bash\n   docker-compose -f docker-compose.yml up -d\n   ```\n\n3. **Reverse Proxy** (Optional)\n   Configure nginx or similar to proxy requests to the container.\n\n### Resource Limits\n\nFor production deployments, consider setting resource limits:\n\n```yaml\nservices:\n  unifi-discord-bridge:\n    deploy:\n      resources:\n        limits:\n          memory: 256M\n          cpus: \"0.5\"\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests if applicable\n5. Submit a pull request\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Support\n\nFor issues and questions:\n\n- Check the troubleshooting section\n- Review application logs\n- Open an issue on GitHub\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbtholt%2Fdiscord-unifi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbtholt%2Fdiscord-unifi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbtholt%2Fdiscord-unifi/lists"}