{"id":51119761,"url":"https://github.com/0xarchit/contestsync","last_synced_at":"2026-06-25T01:00:55.897Z","repository":{"id":358267679,"uuid":"1240717626","full_name":"0xarchit/contestSync","owner":"0xarchit","description":"Sync and track upcoming programming contests across platforms with ease.","archived":false,"fork":false,"pushed_at":"2026-06-07T12:25:55.000Z","size":10032,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T14:14:50.272Z","etag":null,"topics":["atcoder","automation","codeforces","competitive-programming","contest-reminder","contest-scheduler","developer-tools","leetcode"],"latest_commit_sha":null,"homepage":"https://contestsync.0xarchit.is-a.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0xarchit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"0xarchit","buy_me_a_coffee":"0xarchit"}},"created_at":"2026-05-16T13:34:12.000Z","updated_at":"2026-06-07T12:25:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/0xarchit/contestSync","commit_stats":null,"previous_names":["0xarchit/contestsync"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/0xarchit/contestSync","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xarchit%2FcontestSync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xarchit%2FcontestSync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xarchit%2FcontestSync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xarchit%2FcontestSync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0xarchit","download_url":"https://codeload.github.com/0xarchit/contestSync/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xarchit%2FcontestSync/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34755063,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-24T02:00:07.484Z","response_time":106,"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":["atcoder","automation","codeforces","competitive-programming","contest-reminder","contest-scheduler","developer-tools","leetcode"],"created_at":"2026-06-25T01:00:55.171Z","updated_at":"2026-06-25T01:00:55.888Z","avatar_url":"https://github.com/0xarchit.png","language":"Go","funding_links":["https://github.com/sponsors/0xarchit","https://buymeacoffee.com/0xarchit"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/contestSync.webp\" alt=\"ContestSync Logo\" width=\"240\" style=\"border-radius: 24px; box-shadow: 0 10px 40px rgba(0,0,0,0.4);\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eContestSync\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eEnterprise-Grade Open-Source Synchronization Engine \u0026 SaaS Platform for Competitive Programming Calendars.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/0xarchit/contestSync/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/0xarchit/contestSync?style=for-the-badge\u0026logo=github\u0026logoColor=white\u0026labelColor=000000\u0026color=000000\" alt=\"Version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/0xarchit/contestSync/actions\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/0xarchit/contestSync/release.yml?style=for-the-badge\u0026logo=githubactions\u0026logoColor=white\u0026labelColor=000000\u0026color=000000\" alt=\"Build Status\" /\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-000000.svg?style=for-the-badge\u0026logo=opensourceinitiative\u0026logoColor=white\u0026labelColor=000000\u0026color=000000\" alt=\"License\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://go.dev\"\u003e\u003cimg src=\"https://img.shields.io/badge/Go-1.26+-000000.svg?style=for-the-badge\u0026logo=go\u0026logoColor=white\u0026labelColor=000000\u0026color=000000\" alt=\"Go\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\nContestSync is a robust, highly optimized web platform and distributed worker system designed to automatically synchronize competitive programming contests from major platforms directly to Google Calendar. By integrating advanced replication pooling, distributed caching, secure cryptography, and low-latency asset rendering, ContestSync provides developers and competitive programmers with an automated, zero-maintenance scheduling interface.\n\n---\n\n## Supported Platforms \u0026 Integration Specs\n\n| Platform | Scraper/API Type | Fetch Payload Format | Update Frequency | Rate Limit Strategy |\n| :--- | :--- | :--- | :--- | :--- |\n| **LeetCode** | GraphQL Endpoint | JSON Query Payload | Daily Cron Trigger | Dynamic Backoff + Retries |\n| **Codeforces** | REST API Filter | HTTP JSON Response | Daily Cron Trigger | Local Token Bucket Gating |\n| **CodeChef** | REST API Fetcher | Nested JSON Payload | Daily Cron Trigger | Session Connection Pool |\n| **AtCoder** | HTML Scraper | DOM Node Parsing | Daily Cron Trigger | Strict User Agent Gating |\n| **HackerRank** | REST API Fetcher | Flat JSON Document | Daily Cron Trigger | Secure Host Verification |\n| **GeeksforGeeks**| REST API Parser | Raw JSON Payload | Daily Cron Trigger | Bounded Payload Capping |\n| **Naukri Code360**| REST API Parser | Structured JSON Array | Daily Cron Trigger | Dynamic Event Mapping |\n\n---\n\n## Topological System Architecture\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/contestSync_Diagram.gif\" alt=\"ContestSync System Architecture\" width=\"1080\" style=\"border-radius: 24px; box-shadow: 0 10px 40px rgba(0,0,0,0.4);\" /\u003e\n\u003c/p\u003e\n\n---\n\n## Core SaaS \u0026 Enterprise Capabilities\n\n### 1. High-Concurrency Neon DB Read/Write Split Engine\n* **Isolation of Concerns**: Database operations are split into separate Write Primary and multiple Read Replica connection pools.\n* **Atomic Round-Robin Distribution**: Reads are distributed across replicas using lock-free atomic round-robin counters, utilizing the Neon DB pool endpoints for high performance.\n* **Massive Concurrency Support**: Integrates PgBouncer configurations, allowing up to 10,000 concurrent pooled connections per read replica, while direct connections are preserved for write paths and migrations.\n* **In-Memory CA Validation**: Implements in-memory PEM certificate loading for database connections, avoiding disk leakage issues.\n\n### 2. Multi-Tier Distributed Valkey Caching Model\n\n| Caching Area | Cache Key Format | Time To Live (TTL) | Eviction Trigger | Storage Format |\n| :--- | :--- | :--- | :--- | :--- |\n| **Contests List** | `cache:contests:\u003cplatform\u003e` | 12 Hours | Crawler batch finished | JSON Contest Array |\n| **User Preferences** | `cache:user:\u003cuserID\u003e` | 24 Hours | Google OAuth callback / Preferences save / Account deletion | JSON Profile Struct |\n| **Synced Events** | `cache:synced_events:\u003cuserID\u003e` | 24 Hours | End of SyncUser run (if new sync recorded) | JSON String Array |\n| **Platforms List**| `cache:platforms` | 24 Hours | Static Compile (None) | Pre-serialized JSON |\n| **IP Rate Limiter** | `limit:\u003cip_address\u003e:\u003cwindow\u003e` | Variable (Dynamic) | Auto-Expires on window end | Numeric string counter |\n| **User Sessions** | `session:\u003csession_id\u003e` | 7 Days | Account logout | Encoded Gorilla Session |\n\n### 3. Real-Time Contest Overwrite \u0026 Obsolete Contest Pruning\n* **Dynamic Pruning**: When scrapers run, a cleanup operation is executed: `DELETE FROM contests WHERE platform = $1 AND start_time \u003e NOW() AND id != ALL($2)`. This deletes upcoming contests that were rescheduled or cancelled on the host platform.\n* **Boundary Integrity**: The prune query is locked to upcoming contests (`start_time \u003e NOW()`). This preserves past contests and their synced events, preventing redundant event syncs or double-syncing.\n* **Safe Overwrite**: If a scrape returns zero upcoming contests, all future scheduled entries for that platform are deleted.\n\n### 4. Security Controls Matrix (Zero-Trust Security Gating)\n\n| Threat Vector | Security Countermeasure | Implementation Layer | Target Boundary |\n| :--- | :--- | :--- | :--- |\n| **Token Exposure** | AES-256-GCM Cryptographic Envelope | `internal/auth` | Google OAuth Refresh Tokens |\n| **CSRF Exploit** | Session-Bound Verification Gating | `internal/api` | State-Modifying Endpoints (`POST`/`DELETE`) |\n| **Session Fixation** | Complete Session ID Regeneration | `internal/api` | Google Callback Post-Authorization Handshake |\n| **Memory Exhaustion** | Body Limit Constraints \u0026 Monitored Headers | `internal/api` | Capped Request Payload (1MB) / Headers (256B) |\n| **IP Spoofing** | Environment-Gated Trust Gating | `internal/api` | `TRUST_PROXY` Toggle validation |\n\n---\n\n## Detailed System Workflows\n\n### 1. Authentication Lifecycle\n\n```mermaid\nsequenceDiagram\n    autonumber\n    actor User as Competitive Programmer\n    participant Browser as Web Browser\n    participant Server as Server Binary (cmd/server)\n    participant GoogleAuth as Google OAuth Service\n    participant DB_Write as Neon DB Primary\n    participant Valkey as Valkey Distributed Cache\n\n    User-\u003e\u003eBrowser: Click 'Sign in with Google'\n    Browser-\u003e\u003eServer: GET /auth/google\n    Server-\u003e\u003eServer: Generate secure random state token\n    Server-\u003e\u003eDB_Write: Store state: INSERT INTO oauth_states (state)\n    Server-\u003e\u003eBrowser: Set secure HttpOnly 'oauth_state' cookie\n    Server-\u003e\u003eBrowser: Redirect to Google OAuth consent page\n    Browser-\u003e\u003eGoogleAuth: Direct browser request with client_id, scopes, and state\n    GoogleAuth-\u003e\u003eUser: Render permissions consent dialog\n    User-\u003e\u003eGoogleAuth: Authorize request (Calendar \u0026 Profile scopes)\n    GoogleAuth-\u003e\u003eBrowser: Redirect callback: /auth/google/callback?code=CODE\u0026state=STATE\n    Browser-\u003e\u003eServer: GET /auth/google/callback?code=CODE\u0026state=STATE\n    Server-\u003e\u003eServer: Validate state cookie match\n    Server-\u003e\u003eDB_Write: Revalidate \u0026 purge state: DELETE FROM oauth_states WHERE state = STATE\n    DB_Write--\u003e\u003eServer: Return deleted state status\n    Server-\u003e\u003eGoogleAuth: Request tokens: Exchange authorization CODE\n    GoogleAuth--\u003e\u003eServer: Return Access Token \u0026 Refresh Token\n    Server-\u003e\u003eServer: Encrypt Refresh Token using AES-256-GCM\n    Server-\u003e\u003eDB_Write: Upsert User Profile: INSERT/UPDATE users table\n    DB_Write--\u003e\u003eServer: Return active user_id\n    Server-\u003e\u003eValkey: Evict stale profile: DEL cache:user:id\n    Server-\u003e\u003eServer: Rotate and regenerate Session ID\n    Server-\u003e\u003eValkey: Write dynamic session payload: SET session:session_id\n    Server-\u003e\u003eBrowser: Set secure HttpOnly Session cookie\n    Browser-\u003e\u003eUser: Redirect \u0026 render Preferences Dashboard\n```\n\n### 2. Background Synchronization \u0026 Caching Layer\n\n```mermaid\nsequenceDiagram\n    autonumber\n    actor User as Competitive Programmer\n    participant Browser as Web Browser\n    participant Server as Server Binary (cmd/server)\n    participant Queue as Queue Broker (Kafka / Local)\n    participant Worker as Background Worker (cmd/worker)\n    participant Valkey as Valkey Cache\n    participant DB_Read as Neon DB Replicas (Round-Robin)\n    participant DB_Write as Neon DB Primary\n    participant GoogleCal as Google Calendar API\n\n    User-\u003e\u003eBrowser: Click 'Sync Now'\n    Browser-\u003e\u003eServer: POST /sync (with X-CSRF-Token header)\n    Server-\u003e\u003eServer: Verify session \u0026 check CSRF signature\n    Server-\u003e\u003eQueue: Publish sync task: PublishSyncTask(user_id)\n    Server--\u003e\u003eBrowser: Return 202 Accepted response\n    Browser-\u003e\u003eUser: Display 'Syncing in background' UI status\n\n    Queue-\u003e\u003eWorker: Consume sync task: ConsumeSyncTask(user_id)\n    Worker-\u003e\u003eValkey: Acquire lock: SetNX lock:sync:user_id (TTL=5m)\n    alt Lock Acquired successfully\n        Worker-\u003e\u003eValkey: Query cached profile: GET cache:user:user_id\n        alt Cache Hit\n            Valkey--\u003e\u003eWorker: Return profile data\n        else Cache Miss\n            Worker-\u003e\u003eDB_Read: SELECT profile \u0026 encrypted token from Replicas\n            DB_Read--\u003e\u003eWorker: Return database user record\n            Worker-\u003e\u003eValkey: SET cache:user:user_id (24h TTL)\n        end\n        Worker-\u003e\u003eWorker: Decrypt Google OAuth Refresh Token (AES-256-GCM)\n        Worker-\u003e\u003eDB_Write: Update sync status: UPDATE users SET sync_status = 'syncing'\n        Worker-\u003e\u003eGoogleCal: Query primary calendar settings \u0026 verify credentials\n        Worker-\u003e\u003eValkey: Query synced history: GET cache:synced_events:user_id\n        alt Cache Hit\n            Valkey--\u003e\u003eWorker: Return synced contest IDs list\n        else Cache Miss\n            Worker-\u003e\u003eDB_Read: SELECT contest_id FROM synced_events\n            DB_Read--\u003e\u003eWorker: Return synced records list\n            Worker-\u003e\u003eValkey: SET cache:synced_events:user_id (24h TTL)\n        end\n        Worker-\u003e\u003eDB_Read: SELECT future contests: SELECT id FROM contests\n        DB_Read--\u003e\u003eWorker: Return contests list\n        loop For each unsynced future contest\n            Worker-\u003e\u003eWorker: Generate deterministic Base32hex Event ID\n            loop Retry up to 3 times (Exponential Backoff)\n                Worker-\u003e\u003eGoogleCal: Send event insert request\n                GoogleCal--\u003e\u003eWorker: Return 200 OK / 409 Conflict status\n            end\n            alt Event Inserted successfully (200 OK)\n                Worker-\u003e\u003eDB_Write: Log event: INSERT INTO synced_events\n                Worker-\u003e\u003eWorker: Set anySynced = true\n            else Event already exists (409 Conflict)\n                Worker-\u003e\u003eDB_Write: Reconcile event: INSERT INTO synced_events (ON CONFLICT DO NOTHING)\n                Worker-\u003e\u003eWorker: Set anySynced = true\n            end\n        end\n        alt if anySynced is true\n            Worker-\u003e\u003eValkey: Invalidate synced events cache: DEL cache:synced_events:user_id\n        end\n        Worker-\u003e\u003eDB_Write: Log success: UPDATE users SET sync_status = 'success', last_sync_at = NOW()\n        Worker-\u003e\u003eValkey: Release synchronization lock: DEL lock:sync:user_id\n    else Lock is Busy\n        Worker--\u003e\u003eWorker: Task rejected, exit process early\n    end\n```\n\n---\n\n## Codebase Component Topology\n\n```\n[contestSync]\n├── cmd\n│   ├── server  ───────── API Server Binary (Routing, Rate limits, Session stores)\n│   └── worker  ───────── Background Workflows Executor \u0026 Micro-Health Web Server\n├── config  ───────────── Unified Config Engine \u0026 Environment Gating Layer\n├── internal\n│   ├── api  ──────────── HTTP Handlers, Admin routes, Security Middlewares, Asset Minifier\n│   ├── auth  ─────────── Cryptographic AES-256-GCM Encryption/Decryption Modules\n│   ├── db  ───────────── Database Initializer, Pool Splits, Replica Round-Robin counters\n│   ├── extractor  ────── Platform-Specific HTML/JSON Fetchers \u0026 Active Parsers\n│   ├── queue  ────────── Distributed Kafka / Local Fallback Queue Broker\n│   ├── observability  ── Asynchronous Telegram Warnings and Error Diagnostics Telemetry\n│   ├── scheduler  ────── robfig/cron background trigger orchestration\n│   └── sync  ─────────── Synchronization Engine \u0026 Deterministic Google Calendar Sync\n├── migrations  ───────── Database Initialization Schema Definitions\n├── models  ───────────── Global Struct Definitions, Key Formatter \u0026 Cache constants\n└── web  ──────────────── Frontend HTML, GSAP Animations, Lenis, and Custom CSS\n```\n\n---\n\n## Detailed Environment Configurations\n\n| Environment Variable | Description | Default Value | Example Value |\n| :--- | :--- | :--- | :--- |\n| `POSTGRES_DB` | Connection URL for Primary Write Postgres Database | None (Required) | `postgres://user:pass@host:port/db?sslmode=require` |\n| `POSTGRES_READ_DB` | Comma-separated Connection URLs for Read Replica Databases | None | `postgres://user:pass@rep1:port/db,postgres://user:pass@rep2:port/db` |\n| `CONNECTION_LIMIT` | Maximum connections allowed in Primary Write pool | `800` | `20` |\n| `CONNECTION_POOL_LIMIT`| Maximum connections allowed per Read Replica Pool | `10000` | `100` |\n| `VALKEY_URI` | Connection URI string for Valkey instance | None | `rediss://default:password@host:port` |\n| `GOOGLE_CLIENT_ID` | OAuth 2.0 Web Application Client ID from Google Cloud Console | None | `abc-123.apps.googleusercontent.com` |\n| `GOOGLE_CLIENT_SECRET` | OAuth 2.0 Web Application Client Secret from Google Cloud Console | None | `sec_code_xyz` |\n| `GOOGLE_REDIRECT_URL` | Redirect Callback URL registered in Google API credentials | None | `http://localhost:8080/auth/google/callback` |\n| `SESSION_SECRET` | 32-byte hex-encoded key for Gorilla Cookie / Valkey Sessions | None | `d3b07384d113edec49eaa6238ad5ff00` |\n| `ENCRYPTION_KEY` | 32-byte hex-encoded key for AES Refresh Token encryption | None | `2d9bb20065718dfdc0237af8ad3ff49a` |\n| `ADMIN_PASSWORD` | Standard password for admin panel authentication | None | `adm_pwd_secure` |\n| `TRUST_PROXY` | Gated verification trust toggle for client IP forwarding | `false` | `true` |\n| `KAFKA_HOST` | Host Address of Apache Kafka broker | None | `kafka.service.consul` |\n| `KAFKA_PORT` | Port number of Apache Kafka broker | `9092` | `9094` |\n| `KAFKA_PARTITIONS` | Dynamic partition count generated for topics | `2` | `4` |\n| `KAFKA_REPLICATION_FACTOR`| Dynamic replication count set on topic creation | `1` | `2` |\n| `TELEGRAM_PROXY_URL` | Outbound Proxy target for forwarding warnings/errors | None | `https://tg-proxy.myorg.workers.dev` |\n| `PROXY_SECRET_KEY` | Token key for proxy HTTP authorization | None | `sec_key_abc` |\n| `TELEGRAM_GROUP_ID` | Group Identifier target for slog alerts | None | `-1002938475` |\n| `TELEGRAM_GROUP_TOPIC_ID`| Topic Thread ID inside Telemetry Group | None | `12` |\n| `FROM_ENV` | Application node identifier string for diagnostics | None | `Server-Node-Staging` |\n| `PORT` | API Web Server HTTP listener port | `8080` | `7860` |\n| `WORKER_PORT` | Background Worker Micro-Health server HTTP port | `8081` | `8082` |\n| `ENV` | System execution environment gating flag | `production` | `development` |\n\n---\n\n## Execution and Compilation\n\n### Compile and Start API Server Locally\n\n```powershell\n$env:CGO_ENABLED=0; $env:GOOS=\"windows\"; $env:GOARCH=\"amd64\"; $env:GOAMD64=\"v3\"; go build -tags \"netgo osusergo\" -trimpath -buildvcs=false -ldflags=\"-s -w -extldflags -static\" -o server.exe ./cmd/server/main.go 2\u003e\u00261\n./server.exe\n```\n\n### Compile and Start Background Worker Locally\n\n```powershell\n$env:CGO_ENABLED=0; $env:GOOS=\"windows\"; $env:GOARCH=\"amd64\"; $env:GOAMD64=\"v3\"; go build -tags \"netgo osusergo\" -trimpath -buildvcs=false -ldflags=\"-s -w -extldflags -static\" -o worker.exe ./cmd/worker/main.go 2\u003e\u00261\n./worker.exe\n```\n\n### Multi-Service Containerized Deployment\n\nTo build Docker images manually:\n\n```powershell\ndocker build -f Dockerfile.server -t contestsync-server .\ndocker build -f Dockerfile.worker -t contestsync-worker .\n```\n\nTo deploy the entire environment via Docker Compose:\n\n```powershell\ndocker compose up --build\n```\n\n---\n\n## License\n\nMIT © 2026 ContestSync. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xarchit%2Fcontestsync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0xarchit%2Fcontestsync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xarchit%2Fcontestsync/lists"}