{"id":21280358,"url":"https://github.com/tadeasf/threads-bot-api","last_synced_at":"2026-04-10T06:46:21.022Z","repository":{"id":262010666,"uuid":"885957461","full_name":"tadeasf/threads-bot-api","owner":"tadeasf","description":"A NestJS API for automating Threads posts with OAuth2 authentication, Docker support, and comprehensive monitoring. Features secure token handling, CSRF protection, and Kubernetes deployment configurations.","archived":false,"fork":false,"pushed_at":"2024-11-11T23:13:59.000Z","size":202,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-01T11:13:32.943Z","etag":null,"topics":["api","automation","bun","ci-cd","devops","docker","grafana","kubernetes","meta-api","monitoring","nestjs","oauth2","prometheus","social-media","theads-api","typescript"],"latest_commit_sha":null,"homepage":"https://threads.tadeasfort.com","language":"TypeScript","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/tadeasf.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":"2024-11-09T20:50:02.000Z","updated_at":"2024-11-11T23:14:02.000Z","dependencies_parsed_at":"2024-11-09T22:25:10.033Z","dependency_job_id":"5c7104dc-80de-40a8-9865-747b261da267","html_url":"https://github.com/tadeasf/threads-bot-api","commit_stats":null,"previous_names":["tadeasf/threads-bot-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tadeasf/threads-bot-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tadeasf%2Fthreads-bot-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tadeasf%2Fthreads-bot-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tadeasf%2Fthreads-bot-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tadeasf%2Fthreads-bot-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tadeasf","download_url":"https://codeload.github.com/tadeasf/threads-bot-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tadeasf%2Fthreads-bot-api/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265002557,"owners_count":23696076,"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","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":["api","automation","bun","ci-cd","devops","docker","grafana","kubernetes","meta-api","monitoring","nestjs","oauth2","prometheus","social-media","theads-api","typescript"],"created_at":"2024-11-21T10:29:30.591Z","updated_at":"2025-12-30T21:07:14.948Z","avatar_url":"https://github.com/tadeasf.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Threads Bot API\n\nA NestJS API for automating Threads posts with OAuth2 authentication.\n\n## Installation\n\n```bash\nbun install\n```\n\n## Configuration\n\n1. Create a `.env` file in the root directory:\n\n```env\n# App Configuration\nTHREADS_APP_ID=your_app_id\nTHREADS_APP_SECRET=your_app_secret\nTHREADS_REDIRECT_URI=https://threads-bot-api.loca.lt/threads/callback\n```\n\n2. Configure Meta App Settings:\n- Add domain: `https://threads-bot-api.loca.lt`\n- Add to Valid OAuth Redirect URIs: `https://threads-bot-api.loca.lt/threads/callback`\n- Set Match Type: `Match prefix`\n- Set Prefetch: `HTML`\n\n## Running with HTTPS (Development)\n\nThe Threads API requires HTTPS. We use Docker and localtunnel to handle this:\n\n1. Start the services:\n```bash\ndocker-compose up -d\n```\n\n2. Get the tunnel password:\n```bash\n# Check localtunnel logs for the password\ndocker-compose logs localtunnel | grep \"Tunnel Password\"\n```\n\n3. Your API will be available at:\n- HTTPS: https://threads-bot-api.loca.lt\n  - First-time visitors will need the tunnel password\n  - Password is your public IP (shown in localtunnel logs)\n- Local: http://localhost:3000\n\n4. Share the tunnel password with your testers/users\n\n3. Check the logs:\n```bash\n# All services\ndocker-compose logs -f\n\n# Just API\ndocker-compose logs -f api\n\n# Just localtunnel\ndocker-compose logs -f localtunnel\n```\n\n4. Stop the services:\n```bash\ndocker-compose down\n```\n\n## Authentication Flow\n\nThe API implements OAuth2 authentication for Threads with CSRF protection:\n\n1. **Get Authorization URL or Direct Redirect**\n   ```bash\n   # Get URL as JSON\n   curl https://threads-bot-api.loca.lt/threads/auth\n   \n   # Direct redirect to Threads auth page\n   curl -L https://threads-bot-api.loca.lt/threads/auth?redirect=true\n   ```\n\n2. **User Authorization**\n   - User authorizes your app on Threads\n   - Threads redirects back with auth code and state\n\n3. **Exchange Code for Token**\n   ```bash\n   # Handled automatically by callback endpoint\n   GET /threads/callback?code=AUTHORIZATION_CODE\u0026state=STATE_TOKEN\n   ```\n\n4. **Using the Token**\n   ```bash\n   curl -X POST https://threads-bot-api.loca.lt/threads/post \\\n     -H \"Authorization: Bearer YOUR_ACCESS_TOKEN\" \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\n       \"text\": \"Hello from API!\",\n       \"mediaUrls\": [\"https://example.com/image.jpg\"]\n     }'\n   ```\n\n## Development\n\n```bash\n# Run locally\nbun run start:dev\n\n# Run with Docker\ndocker-compose up\n```\n\n## Example Usage\n\n1. Start auth flow (two options):\n```bash\n# Get auth URL\ncurl https://threads-bot-api.loca.lt/threads/auth\n\n# Or redirect directly\ncurl -L https://threads-bot-api.loca.lt/threads/auth?redirect=true\n```\n\n2. Complete authorization on Threads\n\n3. Automatic callback handling with:\n   - CSRF verification\n   - Error handling\n   - Token generation\n\n4. Create a post:\n```bash\ncurl -X POST https://threads-bot-api.loca.lt/threads/post \\\n  -H \"Authorization: Bearer YOUR_ACCESS_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"text\": \"Hello from API!\",\n    \"mediaUrls\": [\"https://example.com/image.jpg\"]\n  }'\n```\n\n## API Documentation\n\n- Swagger UI: http://localhost:3000/api\n- Scalar Docs: http://localhost:3000/docs\n\n## Permissions\n\nThe API requires the following Threads permissions:\n- `threads_basic` - Basic profile access\n- `threads_content_publish` - Ability to create posts\n- `threads_manage_insights` (optional) - Access to post insights\n- `threads_manage_replies` (optional) - Manage post replies\n- `threads_read_replies` (optional) - Read post replies\n\n## Security Features\n\n- CSRF protection with state parameter\n- Environment variable validation\n- Automatic state cleanup (30-minute expiry)\n- Comprehensive error handling\n- Request validation\n- Secure token handling\n\n## Error Handling\n\nThe API handles:\n- Invalid/expired state tokens\n- Missing authorization codes\n- Failed token exchanges\n- Invalid tokens\n- Missing permissions\n- Rate limits\n- Configuration errors\n\n## Security Notes\n\n- Never commit `.env` file\n- Store tokens securely\n- Use HTTPS in production\n- Validate redirect URIs\n- Implement rate limiting\n- Monitor state token usage\n\n## Monitoring\n\nThe API includes built-in monitoring with Grafana and Prometheus:\n\n1. Access dashboards:\n- Grafana: http://localhost:3001 (admin/admin)\n- Prometheus: http://localhost:9090\n\n2. Available metrics:\n- API health status\n- Tunnel connectivity\n- Request rates\n- Error rates\n- Token usage\n- Rate limit status\n\n3. Alerts:\n- Tunnel disconnection\n- High error rates\n- Rate limit warnings\n- Token expiration\n\n## Detailed Deployment Guide\n\n### 1. Initial Setup\n\n1. **Container Registry Setup**\n   ```bash\n   # 1. Login to GitHub Container Registry\n   echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin\n   \n   # 2. Configure Registry Visibility\n   gh api \\\n     --method PUT \\\n     -H \"Accept: application/vnd.github+json\" \\\n     /user/packages/container/threads-bot-api/visibility \\\n     -f visibility='public'\n   ```\n\n2. **Kubernetes Setup**\n   ```bash\n   # 1. Create namespace\n   kubectl create namespace threads-bot\n   \n   # 2. Create secrets\n   kubectl create secret generic threads-bot-secrets \\\n     --from-file=.env.production \\\n     --namespace threads-bot\n   \n   # 3. Apply configurations\n   kubectl apply -f k8s/ --namespace threads-bot\n   ```\n\n3. **SSL/TLS Configuration**\n   ```bash\n   # 1. Install cert-manager\n   kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml\n   \n   # 2. Create ClusterIssuer\n   kubectl apply -f k8s/cert-issuer.yaml\n   \n   # 3. Verify certificates\n   kubectl get certificates -n threads-bot\n   ```\n\n### 2. Development Deployment\n\n1. **Local Development**\n   ```bash\n   # 1. Start with monitoring\n   docker compose -f docker-compose.yml \\\n                 -f docker-compose.monitor.yml \\\n                 up -d\n   \n   # 2. Watch logs\n   docker compose logs -f api\n   \n   # 3. Access services\n   open http://localhost:3000  # API\n   open http://localhost:3001  # Grafana\n   open http://localhost:9090  # Prometheus\n   ```\n\n2. **Preview Environments**\n   ```bash\n   # 1. Create preview\n   ./scripts/deploy.sh --env preview --pr 123\n   \n   # 2. Cleanup preview\n   ./scripts/cleanup-preview.sh --pr 123\n   ```\n\n### 3. Production Deployment\n\n1. **Manual Deployment**\n   ```bash\n   # 1. Build and tag\n   docker build -t ghcr.io/username/threads-bot-api:v1.0.0 .\n   docker push ghcr.io/username/threads-bot-api:v1.0.0\n   \n   # 2. Deploy\n   DEPLOY_ENV=production ./scripts/deploy.sh --version v1.0.0\n   \n   # 3. Verify\n   kubectl get pods -n threads-bot\n   kubectl logs -f deployment/threads-bot -n threads-bot\n   ```\n\n2. **Automated Release**\n   ```bash\n   # 1. Create and push tag\n   git tag v1.0.0\n   git push origin v1.0.0\n   \n   # 2. Monitor workflow\n   gh workflow view release\n   \n   # 3. Verify deployment\n   ./scripts/verify-deployment.sh v1.0.0\n   ```\n\n### 4. Rollback Procedures\n\n1. **Automatic Rollback**\n   ```bash\n   # Triggered on failed health checks\n   ./scripts/rollback.sh --last-stable\n   ```\n\n2. **Manual Rollback**\n   ```bash\n   # To specific version\n   ./scripts/rollback.sh --version v0.9.0\n   \n   # Verify rollback\n   curl https://your-domain.com/health\n   ```\n\n## Monitoring Setup\n\n### 1. Grafana Dashboards\n\n1. **API Overview Dashboard**\n   ```json\n   {\n     \"title\": \"API Overview\",\n     \"panels\": [\n       {\n         \"title\": \"Request Rate\",\n         \"type\": \"graph\",\n         \"datasource\": \"Prometheus\",\n         \"targets\": [\n           {\n             \"expr\": \"rate(http_requests_total[5m])\"\n           }\n         ]\n       },\n       {\n         \"title\": \"Error Rate\",\n         \"type\": \"graph\",\n         \"targets\": [\n           {\n             \"expr\": \"rate(http_errors_total[5m])\"\n           }\n         ]\n       },\n       {\n         \"title\": \"Response Time\",\n         \"type\": \"gauge\",\n         \"targets\": [\n           {\n             \"expr\": \"http_request_duration_seconds\"\n           }\n         ]\n       }\n     ]\n   }\n   ```\n\n2. **Tunnel Status Dashboard**\n   ```json\n   {\n     \"title\": \"Tunnel Status\",\n     \"panels\": [\n       {\n         \"title\": \"Tunnel Uptime\",\n         \"type\": \"stat\",\n         \"targets\": [\n           {\n             \"expr\": \"tunnel_uptime_seconds\"\n           }\n         ]\n       },\n       {\n         \"title\": \"Connection Issues\",\n         \"type\": \"timeseries\",\n         \"targets\": [\n           {\n             \"expr\": \"tunnel_connection_errors_total\"\n           }\n         ]\n       }\n     ]\n   }\n   ```\n\n### 2. Alert Rules\n\n1. **API Alerts**\n   ```yaml\n   groups:\n     - name: api\n       rules:\n         - alert: HighErrorRate\n           expr: rate(http_errors_total[5m]) \u003e 0.1\n           for: 5m\n           labels:\n             severity: critical\n         - alert: SlowResponses\n           expr: http_request_duration_seconds \u003e 2\n           for: 5m\n           labels:\n             severity: warning\n   ```\n\n2. **Tunnel Alerts**\n   ```yaml\n   groups:\n     - name: tunnel\n       rules:\n         - alert: TunnelDown\n           expr: tunnel_up == 0\n           for: 1m\n           labels:\n             severity: critical\n         - alert: TunnelLatency\n           expr: tunnel_latency_seconds \u003e 1\n           for: 5m\n           labels:\n             severity: warning\n   ```\n\n### 3. Monitoring Access\n\n1. **Local Access**\n   ```bash\n   # Grafana\n   open http://localhost:3001\n   # Default credentials: admin/admin\n   \n   # Prometheus\n   open http://localhost:9090\n   \n   # AlertManager\n   open http://localhost:9093\n   ```\n\n2. **Production Access**\n   ```bash\n   # Port forward services\n   kubectl port-forward svc/grafana 3001:3000 -n monitoring\n   kubectl port-forward svc/prometheus 9090:9090 -n monitoring\n   kubectl port-forward svc/alertmanager 9093:9093 -n monitoring\n   ```\n\n## CI/CD Configuration\n\n### GitHub Actions Workflows\n\n1. **Pull Request (`pr.yml`)**\n   - Triggered on PRs to main branch\n   - Runs tests, lint, and type checks using Bun\n   - Creates preview deployment\n   - Required secrets: `DOCKER_REGISTRY`\n\n2. **Main Branch (`main.yml`)**\n   - Triggered on pushes to main\n   - Builds and deploys to production\n   - Runs smoke tests\n   - Automatic rollback on failure\n   - Required secrets:\n     - `DOCKER_REGISTRY`\n     - `KUBECONFIG`\n     - `PRODUCTION_URL`\n\n3. **Security Scan (`security.yml`)**\n   - Daily security scans\n   - Runs on main branch pushes\n   - Uses Trivy and CodeQL\n   - Creates issues for vulnerabilities\n   - Required secrets: None\n   - Required variables:\n     - `DOCKER_REGISTRY`\n\n4. **Release (`release.yml`)**\n   - Triggered on version tags (`v*`)\n   - Creates GitHub releases\n   - Builds and tags Docker images\n   - Required secrets: `DOCKER_REGISTRY`\n\n5. **Monitoring (`monitor.yml`)**\n   - Runs health checks every 5 minutes\n   - Creates issues for failures\n   - Required secrets: `PRODUCTION_URL`\n\n### Required Secrets Setup\n\n1. **GitHub Repository Secrets**\n   ```bash\n   # Container Registry\n   DOCKER_REGISTRY=ghcr.io/your-username\n   \n   # Kubernetes Config (base64 encoded)\n   KUBECONFIG=\u003cbase64-encoded-kubeconfig\u003e\n   \n   # Production URL\n   PRODUCTION_URL=https://your-domain.com\n   ```\n\n2. **How to Get Secrets**:\n   - `DOCKER_REGISTRY`: \n     - Use GitHub Container Registry: `ghcr.io/username`\n     - Or Docker Hub: `docker.io/username`\n   \n   - `KUBECONFIG`:\n     ```bash\n     # Encode your kubeconfig\n     base64 -i ~/.kube/config\n     ```\n   \n   - `PRODUCTION_URL`: Your production domain\n\n### Deployment Scripts\n\n1. **Deploy Script (`scripts/deploy.sh`)**\n   ```bash\n   # Development deployment\n   DEPLOY_ENV=development ./scripts/deploy.sh\n   \n   # Production deployment\n   DEPLOY_ENV=production ./scripts/deploy.sh\n   ```\n   \n   Features:\n   - Environment validation\n   - Dependency checks\n   - Health monitoring\n   - Colored output\n   - Error handling\n\n2. **Rollback Script (`scripts/rollback.sh`)**\n   ```bash\n   # Rollback to specific version\n   ./scripts/rollback.sh --version v1.2.3\n   \n   # Rollback to last stable\n   ./scripts/rollback.sh --last-stable\n   ```\n   \n   Features:\n   - Version management\n   - Automatic backup\n   - Health verification\n   - Cleanup of old backups\n\n### Docker Configuration\n\n1. **Development Setup**\n   ```yaml\n   # docker-compose.yml\n   services:\n     api:\n       build: \n         target: development\n       volumes:\n         - .:/app\n     tunnel:\n       profiles: [\"development\"]\n   ```\n\n2. **Production Setup**\n   ```yaml\n   # docker-compose.prod.yml\n   services:\n     api:\n       build:\n         target: production\n       restart: always\n     monitoring:\n       image: prom/prometheus\n     grafana:\n       image: grafana/grafana\n   ```\n\n3. **Monitoring Setup**\n   ```yaml\n   # docker-compose.monitor.yml\n   services:\n     prometheus:\n       volumes:\n         - ./monitoring/prometheus:/etc/prometheus\n     grafana:\n       volumes:\n         - ./monitoring/grafana:/etc/grafana\n     alertmanager:\n       image: prom/alertmanager\n   ```\n\n### Environment Files\n\n1. **Development**\n   ```env\n   # .env.development\n   NODE_ENV=development\n   TUNNEL_SUBDOMAIN=threads-bot-api\n   MONITOR_ENABLED=true\n   ```\n\n2. **Production**\n   ```env\n   # .env.production\n   NODE_ENV=production\n   PRODUCTION_URL=https://your-domain.com\n   MONITOR_ENABLED=true\n   ALERT_WEBHOOK=https://your-webhook.com\n   ```\n\n3. **Monitoring**\n   ```env\n   # .env.monitor\n   GRAFANA_ADMIN_PASSWORD=your_secure_password\n   PROMETHEUS_RETENTION=15d\n   ALERT_CHANNELS=slack,email\n   ```\n\n### Quick Start\n\n1. **Setup Repository**\n   ```bash\n   # 1. Add GitHub Secrets\n   gh secret set DOCKER_REGISTRY -b \"ghcr.io/username\"\n   gh secret set KUBECONFIG -b \"$(base64 -i ~/.kube/config)\"\n   gh secret set PRODUCTION_URL -b \"https://your-domain.com\"\n   \n   # 2. Create environments\n   cp .env.example .env.development\n   cp .env.example .env.production\n   \n   # 3. Start development\n   DEPLOY_ENV=development ./scripts/deploy.sh\n   ```\n\n2. **Monitor Deployment**\n   ```bash\n   # View logs\n   docker-compose logs -f\n   \n   # Check metrics\n   open http://localhost:3001\n   \n   # View alerts\n   open http://localhost:9093\n   ```\n\nThis project was created using `bun init` in bun v1.1.29. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftadeasf%2Fthreads-bot-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftadeasf%2Fthreads-bot-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftadeasf%2Fthreads-bot-api/lists"}