diff --git a/README.md b/README.md index b136e0b..2c1b1f0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@
flag -

CDN

-

A CDN solution for Hack Club!

+

cdn.hackclub.com

Deep under the waves and storms there lies a vault...

@@ -15,111 +14,10 @@ -## 🚀 Features - -- **Multi-version API Support** (v1, v2, v3) -- **Slack Bot Integration** - - Upload up to 10 files per message - - Automatic file sanitization - - file organization -- **Secure API Endpoints** -- **Cost-Effective Storage** (87-98% cost reduction vs. Vercel CDN) -- **Prevent File Deduplication** -- **Organized Storage Structure** - -## 🔧 Setup - -### 1. Slack App Configuration - -1. Create a new Slack App at [api.slack.com](https://api.slack.com/apps) -2. Enable Socket Mode in the app settings -3. Add the following Bot Token Scopes: - - `channels:history` - - `channels:read` - - `chat:write` - - `files:read` - - `files:write` - - `groups:history` - - `reactions:write` -4. Enable Event Subscriptions and subscribe to `file_shared` event -5. Install the app to your workspace - -### 2. Storage Configuration - -This CDN supports any S3-compatible storage service. Here's how to set it up using Cloudflare R2 as an example: - -#### Setting up Cloudflare R2 (Example) - -1. **Create R2 Bucket** - - Go to Cloudflare Dashboard > R2 - - Click "Create Bucket" - - Name your bucket - - Enable public access - -2. **Generate API Credentials** - - Go to R2 - - Click "Manage API tokens" in API - - Click "Create API Token" - - Permissions: "Object Read & Write" - - Save both Access Key ID and Secret Access Key (S3) - -3. **Get Your URL** - - Go to R2 - - Click "Use R2 with APIs" in API - - Select S3 Compatible API - - The URL is your Endpoint - - -4. **Configure Custom Domain (Optional)** - - Go to R2 > Bucket Settings > Custom Domains - - Add your domain (e.g., cdn.beans.com) - - Follow DNS configuration steps - -### 3. Environment Setup - -Check out the `example.env` file for getting started! - -### **4. Installation & Running** - -#### **Install Dependencies** -Make sure you have [Bun](https://bun.sh/) installed, then run: - -```bash -bun install -``` - -#### **Run the Application** -You can start the application using any of the following methods: - -```bash -# Using Node.js -node index.js - -# Using Bun -bun index.js - -# Using Bun with script -bun run start -``` - -#### **Using PM2 (Optional)** -For auto-starting the application, you can use PM2: - -```bash -pm2 start bun --name "HC-CDN1" -- run start - -# Optionally, save the process list -pm2 save - -# Optionally, generate startup script -pm2 startup -``` ## 📡 API Usage -⚠️ **IMPORTANT SECURITY NOTE**: - All API endpoints require authentication via `Authorization: Bearer api-token` header -- This includes all versions (v1, v2, v3) - no exceptions! - Use the API_TOKEN from your environment configuration - Failure to include a valid token will result in 401 Unauthorized responses @@ -141,8 +39,7 @@ curl --location 'https://cdn.hackclub.com/api/v3/new' \ --header 'Content-Type: application/json' \ --data '[ "https://assets.hackclub.com/flag-standalone.svg", - "https://assets.hackclub.com/flag-orpheus-left.png", - "https://assets.hackclub.com/icon-progress-marker.svg" + "https://assets.hackclub.com/flag-orpheus-left.png" ]' ``` @@ -151,31 +48,19 @@ curl --location 'https://cdn.hackclub.com/api/v3/new' \ { "files": [ { - "deployedUrl": "https://cdn.example.dev/s/v3/3e48b91a4599a3841c028e9a683ef5ce58cea372_flag-standalone.svg", - "file": "0_16361167e11b0d172a47e726b40d70e9873c792b_upload_1736985095691", - "sha": "16361167e11b0d172a47e726b40d70e9873c792b", - "size": 90173 + "deployedUrl": "https://hc-cdn.hel1.your-objectstorage.com/s/v3/64a9472006c4472d7ac75f2d4d9455025d9838d6_flag-standalone.svg", + "file": "0_64a9472006c4472d7ac75f2d4d9455025d9838d6_flag-standalone.svg", + "sha": "64a9472006c4472d7ac75f2d4d9455025d9838d6", + "size": 4365 }, { - "deployedUrl": "https://cdn.example.dev/s/v3/4e48b91a4599a3841c028e9a683ef5ce58cea372_flag-orpheus-left.png", - "file": "1_16361167e11b0d172a47e726b40d70e9873c792b_upload_1736985095692", - "sha": "16361167e11b0d172a47e726b40d70e9873c792b", - "size": 80234 - }, - { - "deployedUrl": "https://cdn.example.dev/s/v3/5e48b91a4599a3841c028e9a683ef5ce58cea372_icon-progress-marker.svg", - "file": "2_16361167e11b0d172a47e726b40d70e9873c792b_upload_1736985095693", - "sha": "16361167e11b0d172a47e726b40d70e9873c792b", - "size": 70345 - }, - { - "deployedUrl": "https://cdn.example.dev/s/v3/6e48b91a4599a3841c028e9a683ef5ce58cea372_flag-orpheus-right.png", - "file": "3_16361167e11b0d172a47e726b40d70e9873c792b_upload_1736985095694", - "sha": "16361167e11b0d172a47e726b40d70e9873c792b", - "size": 60456 + "deployedUrl": "https://hc-cdn.hel1.your-objectstorage.com/s/v3/d926bfd9811ebfe9172187793a171a5cbcc61992_flag-orpheus-left.png", + "file": "1_d926bfd9811ebfe9172187793a171a5cbcc61992_flag-orpheus-left.png", + "sha": "d926bfd9811ebfe9172187793a171a5cbcc61992", + "size": 8126 } ], - "cdnBase": "https://cdn.example.dev" + "cdnBase": "https://hc-cdn.hel1.your-objectstorage.com" } ``` @@ -196,8 +81,7 @@ Content-Type: application/json ```json [ "https://assets.hackclub.com/flag-standalone.svg", - "https://assets.hackclub.com/flag-orpheus-left.png", - "https://assets.hackclub.com/icon-progress-marker.svg" + "https://assets.hackclub.com/flag-orpheus-left.png" ] ``` @@ -205,8 +89,7 @@ Content-Type: application/json ```json { "flag-standalone.svg": "https://cdn.example.dev/s/v2/flag-standalone.svg", - "flag-orpheus-left.png": "https://cdn.example.dev/s/v2/flag-orpheus-left.png", - "icon-progress-marker.svg": "https://cdn.example.dev/s/v2/icon-progress-marker.svg" + "flag-orpheus-left.png": "https://cdn.example.dev/s/v2/flag-orpheus-left.png" } ``` @@ -228,8 +111,7 @@ Content-Type: application/json ```json [ "https://assets.hackclub.com/flag-standalone.svg", - "https://assets.hackclub.com/flag-orpheus-left.png", - "https://assets.hackclub.com/icon-progress-marker.svg" + "https://assets.hackclub.com/flag-orpheus-left.png" ] ``` @@ -237,49 +119,17 @@ Content-Type: application/json ```json [ "https://cdn.example.dev/s/v1/0_flag-standalone.svg", - "https://cdn.example.dev/s/v1/1_flag-orpheus-left.png", - "https://cdn.example.dev/s/v1/2_icon-progress-marker.svg" + "https://cdn.example.dev/s/v1/1_flag-orpheus-left.png" ] ``` -## 🤖 Slack Bot Features - -- **Multi-file Upload:** Upload up to 10 files in a single message no more than 3 messages at a time! -- **File Organization:** Files are stored as `/s/{slackUserId}/{timestamp}_{sanitizedFilename}` -- **Error Handling:** Error Handeling -- **File Sanitization:** Automatic filename cleaning -- **Size Limits:** Enforces files to be under 2GB - -## Legacy API Notes -- V1 and V2 APIs are maintained for backwards compatibility -- All versions now require authentication via Bearer token -- We recommend using V3 API for new implementations - -## Technical Details +# Technical Details - **Storage Structure:** `/s/v3/{HASH}_{filename}` - **File Naming:** `/s/{slackUserId}/{unix}_{sanitizedFilename}` -- **Cost Efficiency:** Uses object storage for significant cost savings -- **Security:** Token-based authentication for API access - -## 💻 Slack Bot Behavior - -- Reacts to file uploads with status emojis: - - ⏳ Processing - - ✅ Success - - ❌ Error -- Supports up to 10 files per message -- Max 3 messages concurrently! -- Maximum file size: 2GB per file - -## 💰 Cost Optimization - -- Uses Object storage -- 87-98% cost reduction compared to Vercel CDN

Made with 💜 for Hack Club

-

All illustrations by @maxwofford

\ No newline at end of file