Spaces:
Sleeping
Sleeping
deploy v0.3
Browse files
.env
CHANGED
|
@@ -3,7 +3,7 @@ DB_PORT=3306
|
|
| 3 |
DB_USER=academyc_root_pp
|
| 4 |
DB_PASS=Langkahpemula123
|
| 5 |
DB_NAME=academyc_moodlink
|
| 6 |
-
PORT=
|
| 7 |
|
| 8 |
# JWT
|
| 9 |
JWT_SECRET=a7f278d3443f86d9625fd1192b90502e95c285929f94e213e1472c4a369d6e5c
|
|
|
|
| 3 |
DB_USER=academyc_root_pp
|
| 4 |
DB_PASS=Langkahpemula123
|
| 5 |
DB_NAME=academyc_moodlink
|
| 6 |
+
PORT=7860
|
| 7 |
|
| 8 |
# JWT
|
| 9 |
JWT_SECRET=a7f278d3443f86d9625fd1192b90502e95c285929f94e213e1472c4a369d6e5c
|
README.md
CHANGED
|
@@ -1,595 +1,9 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
- **Gamification**: Points and level system with streak bonuses
|
| 11 |
-
- **Achievements System**: Badge system with various challenges
|
| 12 |
-
- **Anonymous Feed**: View recent mood entries from other users
|
| 13 |
-
- **Realtime Updates**: WebSocket support for live feed updates
|
| 14 |
-
- **Support System**: Send emotional support reactions to journal entries
|
| 15 |
-
- **Push Notifications**: FCM-based notifications for support and reminders
|
| 16 |
-
- **Dashboard**: User statistics and progress tracking
|
| 17 |
-
- **Rate Limiting**: Protect sensitive endpoints from abuse
|
| 18 |
-
- **WebSocket Notifications**: Realtime support notifications to users
|
| 19 |
-
- **Global Statistics**: System-wide analytics and insights
|
| 20 |
-
- **Content Moderation**: Report and manage inappropriate content
|
| 21 |
-
- **Automated Moderation**: Content filtering with configurable terms
|
| 22 |
-
- **Location-Based Feed**: Filter feed entries by geographic proximity
|
| 23 |
-
- **Account Reset**: Complete data deletion and new UUID generation
|
| 24 |
-
|
| 25 |
-
## API Endpoints
|
| 26 |
-
|
| 27 |
-
### Authentication
|
| 28 |
-
- `POST /api/v1/user/register` - Create new anonymous user
|
| 29 |
-
- `GET /api/v1/user/me` - Get user profile (requires User-ID header)
|
| 30 |
-
- `POST /api/v1/auth/google` - Link Google account to UUID
|
| 31 |
-
- `POST /api/v1/auth/restore` - Restore UUID from Google account
|
| 32 |
-
|
| 33 |
-
### Mood Tracking
|
| 34 |
-
- `POST /api/v1/checkin` - Submit daily mood check-in
|
| 35 |
-
- `GET /api/v1/checkin/today` - Check if user has checked in today
|
| 36 |
-
|
| 37 |
-
### Feed
|
| 38 |
-
- `GET /api/v1/feed` - Get recent mood entries (supports pagination)
|
| 39 |
-
- Optional query parameters: `lat`, `lng`, `radius_km` for location filtering
|
| 40 |
-
- `WS /ws/feed` - WebSocket connection for realtime feed updates
|
| 41 |
-
- Requires `user_id` query parameter for targeted notifications
|
| 42 |
-
|
| 43 |
-
### Support
|
| 44 |
-
- `POST /api/v1/support` - Send support reaction to journal entry
|
| 45 |
-
|
| 46 |
-
### Comments
|
| 47 |
-
- `POST /api/v1/comment` - Add comment to journal entry
|
| 48 |
-
- `GET /api/v1/comment/:journal_id` - Get comments for journal entry
|
| 49 |
-
- `POST /api/v1/comment/report` - Report inappropriate comment
|
| 50 |
-
- `GET /api/v1/comment/flagged` - Get flagged comments (admin only)
|
| 51 |
-
|
| 52 |
-
### Bookmarks
|
| 53 |
-
- `POST /api/v1/bookmark` - Bookmark a journal entry
|
| 54 |
-
- `GET /api/v1/bookmark/list` - Get user's bookmarks
|
| 55 |
-
- `DELETE /api/v1/bookmark/:id` - Remove bookmark
|
| 56 |
-
|
| 57 |
-
### Tags
|
| 58 |
-
- `GET /api/v1/tags/trending` - Get trending tags from recent entries
|
| 59 |
-
|
| 60 |
-
### Anonymous Chat
|
| 61 |
-
- `POST /api/v1/chat/start` - Start or join anonymous chat
|
| 62 |
-
- `POST /api/v1/chat/:room_id/message` - Send message in chat room
|
| 63 |
-
- `GET /api/v1/chat/:room_id/messages` - Get chat messages
|
| 64 |
-
- `DELETE /api/v1/chat/:room_id/end` - End chat room
|
| 65 |
-
- `GET /api/v1/chat/active` - Get active chat rooms for user
|
| 66 |
-
|
| 67 |
-
### AI Reflection
|
| 68 |
-
- `POST /api/v1/ai/reflect` - Get AI-powered emotional reflection
|
| 69 |
-
- `GET /api/v1/ai/history` - Get reflection history
|
| 70 |
-
|
| 71 |
-
### Search & Filter
|
| 72 |
-
- `GET /api/v1/search` - Search and filter journal entries
|
| 73 |
-
- Query parameters: `mood`, `keyword`, `date_from`, `date_to`, `page`, `limit`
|
| 74 |
-
- `GET /api/v1/search/moods` - Get available mood filters
|
| 75 |
-
- `GET /api/v1/search/keywords` - Get popular keywords from recent entries
|
| 76 |
-
|
| 77 |
-
### Story System
|
| 78 |
-
- `GET /api/v1/story-categories` - Get story categories
|
| 79 |
-
- `GET /api/v1/stories` - Get stories by category
|
| 80 |
-
- Query parameters: `category`, `page`, `limit`
|
| 81 |
-
- `POST /api/v1/story/submit` - Submit a story for approval
|
| 82 |
-
- `GET /api/v1/story/my-stories` - Get user's submitted stories
|
| 83 |
-
|
| 84 |
-
### Mood Missions
|
| 85 |
-
- `GET /api/v1/mood-mission` - Get daily mission based on user's mood
|
| 86 |
-
- `POST /api/v1/mood-mission/complete` - Complete a mission
|
| 87 |
-
- `GET /api/v1/mood-mission/history` - Get mission completion history
|
| 88 |
-
- `GET /api/v1/mood-mission/stats` - Get mission statistics
|
| 89 |
-
|
| 90 |
-
### Journal Capsules (Time-locked)
|
| 91 |
-
- `POST /api/v1/journal/future` - Create a time-locked journal capsule
|
| 92 |
-
- `GET /api/v1/journal/future/list` - Get user's capsules
|
| 93 |
-
- Query parameters: `status` (locked/unlocked/opened), `page`, `limit`
|
| 94 |
-
- `POST /api/v1/journal/future/:capsule_id/open` - Open an unlocked capsule
|
| 95 |
-
- `DELETE /api/v1/journal/future/:capsule_id` - Delete a capsule
|
| 96 |
-
- `GET /api/v1/journal/future/stats` - Get capsule statistics
|
| 97 |
-
|
| 98 |
-
### Dashboard
|
| 99 |
-
- `GET /api/v1/dashboard/:user_id` - Get user dashboard data
|
| 100 |
-
- `GET /api/v1/user/stats` - Get detailed user statistics
|
| 101 |
-
|
| 102 |
-
### User Management
|
| 103 |
-
- `PATCH /api/v1/user/profile` - Update user profile (display name, avatar, theme)
|
| 104 |
-
- `GET /api/v1/user/export` - Export all user data
|
| 105 |
-
- `POST /api/v1/user/reset` - Reset account and delete all data
|
| 106 |
-
- `POST /api/v1/streak/recover` - Recover streak using points (50 points)
|
| 107 |
-
|
| 108 |
-
### Achievements
|
| 109 |
-
- `GET /api/v1/achievements/:user_id` - Get user achievements
|
| 110 |
-
|
| 111 |
-
### Push Notifications
|
| 112 |
-
- `POST /api/v1/device-token` - Register FCM device token
|
| 113 |
-
- `DELETE /api/v1/device-token` - Unregister FCM device token
|
| 114 |
-
- `POST /api/v1/notify/:user_id` - Send custom notification (admin only)
|
| 115 |
-
|
| 116 |
-
### Statistics
|
| 117 |
-
- `GET /api/v1/stats/global` - Get global system statistics
|
| 118 |
-
- `GET /api/v1/leaderboard` - Get leaderboard by level, points, or streak
|
| 119 |
-
|
| 120 |
-
### Moderation
|
| 121 |
-
- `POST /api/v1/report` - Report inappropriate journal entry
|
| 122 |
-
- `GET /api/v1/reports` - List reports (admin only, requires `Is-Admin: true` header)
|
| 123 |
-
- `GET /api/v1/moderation/flagged` - List flagged entries (admin only)
|
| 124 |
-
- `PUT /api/v1/moderation/unflag/:entry_id` - Unflag entry (admin only)
|
| 125 |
-
|
| 126 |
-
## Database Schema
|
| 127 |
-
|
| 128 |
-
### anonymous_users
|
| 129 |
-
- `id` (UUID, PRIMARY KEY)
|
| 130 |
-
- `google_id` (VARCHAR, NULLABLE, UNIQUE)
|
| 131 |
-
- `is_synced` (BOOLEAN, DEFAULT false)
|
| 132 |
-
- `display_name` (VARCHAR, DEFAULT 'Anonymous')
|
| 133 |
-
- `avatar_type` (VARCHAR, DEFAULT 'default')
|
| 134 |
-
- `theme` (VARCHAR, DEFAULT 'light')
|
| 135 |
-
- `color_tone` (VARCHAR, DEFAULT 'blue')
|
| 136 |
-
- `created_at` (DATETIME)
|
| 137 |
-
- `points` (INT, DEFAULT 0)
|
| 138 |
-
- `level` (INT, DEFAULT 1)
|
| 139 |
-
- `last_checkin` (DATE)
|
| 140 |
-
|
| 141 |
-
### mood_entries
|
| 142 |
-
- `id` (UUID, PRIMARY KEY)
|
| 143 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 144 |
-
- `mood` (ENUM: 'happy','sad','tired','angry','anxious','neutral')
|
| 145 |
-
- `note` (TEXT)
|
| 146 |
-
- `is_flagged` (BOOLEAN, DEFAULT false)
|
| 147 |
-
- `is_private` (BOOLEAN, DEFAULT false)
|
| 148 |
-
- `tags` (TEXT, JSON array as string)
|
| 149 |
-
- `location_lat` (FLOAT)
|
| 150 |
-
- `location_lng` (FLOAT)
|
| 151 |
-
- `created_at` (DATETIME)
|
| 152 |
-
|
| 153 |
-
### journal_supports
|
| 154 |
-
- `id` (INT, PRIMARY KEY)
|
| 155 |
-
- `journal_id` (UUID, FOREIGN KEY)
|
| 156 |
-
- `type` (ENUM: 'heart','hug','pray')
|
| 157 |
-
- `created_at` (DATETIME)
|
| 158 |
-
|
| 159 |
-
### journal_reports
|
| 160 |
-
- `id` (UUID, PRIMARY KEY)
|
| 161 |
-
- `journal_id` (UUID, FOREIGN KEY)
|
| 162 |
-
- `reason` (VARCHAR)
|
| 163 |
-
- `created_at` (DATETIME)
|
| 164 |
-
|
| 165 |
-
### user_achievements
|
| 166 |
-
- `id` (INT, PRIMARY KEY)
|
| 167 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 168 |
-
- `badge_name` (VARCHAR)
|
| 169 |
-
- `earned_at` (DATETIME)
|
| 170 |
-
|
| 171 |
-
### device_tokens
|
| 172 |
-
- `id` (INT, PRIMARY KEY)
|
| 173 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 174 |
-
- `token` (TEXT)
|
| 175 |
-
- `created_at` (DATETIME)
|
| 176 |
-
- `updated_at` (DATETIME)
|
| 177 |
-
|
| 178 |
-
### journal_comments
|
| 179 |
-
- `id` (UUID, PRIMARY KEY)
|
| 180 |
-
- `journal_id` (UUID, FOREIGN KEY)
|
| 181 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 182 |
-
- `comment` (TEXT)
|
| 183 |
-
- `is_flagged` (BOOLEAN, DEFAULT false)
|
| 184 |
-
- `created_at` (DATETIME)
|
| 185 |
-
|
| 186 |
-
### comment_reports
|
| 187 |
-
- `id` (UUID, PRIMARY KEY)
|
| 188 |
-
- `comment_id` (UUID, FOREIGN KEY)
|
| 189 |
-
- `reporter_id` (UUID, FOREIGN KEY)
|
| 190 |
-
- `reason` (VARCHAR)
|
| 191 |
-
- `created_at` (DATETIME)
|
| 192 |
-
|
| 193 |
-
### bookmarks
|
| 194 |
-
- `id` (UUID, PRIMARY KEY)
|
| 195 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 196 |
-
- `journal_id` (UUID, FOREIGN KEY)
|
| 197 |
-
- `created_at` (DATETIME)
|
| 198 |
-
|
| 199 |
-
### chat_rooms
|
| 200 |
-
- `id` (UUID, PRIMARY KEY)
|
| 201 |
-
- `user_a` (UUID, FOREIGN KEY)
|
| 202 |
-
- `user_b` (UUID, FOREIGN KEY)
|
| 203 |
-
- `is_active` (BOOLEAN, DEFAULT true)
|
| 204 |
-
- `created_at` (DATETIME)
|
| 205 |
-
- `updated_at` (DATETIME)
|
| 206 |
-
|
| 207 |
-
### chat_messages
|
| 208 |
-
- `id` (UUID, PRIMARY KEY)
|
| 209 |
-
- `room_id` (UUID, FOREIGN KEY)
|
| 210 |
-
- `sender_id` (UUID, FOREIGN KEY)
|
| 211 |
-
- `message` (TEXT)
|
| 212 |
-
- `created_at` (DATETIME)
|
| 213 |
-
|
| 214 |
-
### ai_reflections
|
| 215 |
-
- `id` (UUID, PRIMARY KEY)
|
| 216 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 217 |
-
- `question` (TEXT)
|
| 218 |
-
- `answer` (TEXT)
|
| 219 |
-
- `mood_context` (VARCHAR)
|
| 220 |
-
- `is_private` (BOOLEAN, DEFAULT false)
|
| 221 |
-
- `created_at` (DATETIME)
|
| 222 |
-
|
| 223 |
-
### story_categories
|
| 224 |
-
- `id` (INT, PRIMARY KEY)
|
| 225 |
-
- `name` (VARCHAR, UNIQUE)
|
| 226 |
-
- `display_name` (VARCHAR)
|
| 227 |
-
- `description` (TEXT)
|
| 228 |
-
- `icon` (VARCHAR)
|
| 229 |
-
- `created_at` (DATETIME)
|
| 230 |
-
|
| 231 |
-
### stories
|
| 232 |
-
- `id` (UUID, PRIMARY KEY)
|
| 233 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 234 |
-
- `category_id` (INT, FOREIGN KEY)
|
| 235 |
-
- `title` (VARCHAR)
|
| 236 |
-
- `content` (TEXT)
|
| 237 |
-
- `mood` (ENUM)
|
| 238 |
-
- `status` (ENUM: 'pending','approved','rejected')
|
| 239 |
-
- `is_flagged` (BOOLEAN, DEFAULT false)
|
| 240 |
-
- `created_at` (DATETIME)
|
| 241 |
-
|
| 242 |
-
### mood_missions
|
| 243 |
-
- `id` (INT, PRIMARY KEY)
|
| 244 |
-
- `mood` (ENUM)
|
| 245 |
-
- `title` (VARCHAR)
|
| 246 |
-
- `description` (TEXT)
|
| 247 |
-
- `points` (INT, DEFAULT 15)
|
| 248 |
-
- `is_active` (BOOLEAN, DEFAULT true)
|
| 249 |
-
- `created_at` (DATETIME)
|
| 250 |
-
|
| 251 |
-
### user_mission_completions
|
| 252 |
-
- `id` (UUID, PRIMARY KEY)
|
| 253 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 254 |
-
- `mission_id` (INT, FOREIGN KEY)
|
| 255 |
-
- `note` (TEXT)
|
| 256 |
-
- `created_at` (DATETIME)
|
| 257 |
-
|
| 258 |
-
### journal_capsules
|
| 259 |
-
- `id` (UUID, PRIMARY KEY)
|
| 260 |
-
- `user_id` (UUID, FOREIGN KEY)
|
| 261 |
-
- `title` (VARCHAR)
|
| 262 |
-
- `content` (TEXT)
|
| 263 |
-
- `unlock_at` (DATETIME)
|
| 264 |
-
- `is_opened` (BOOLEAN, DEFAULT false)
|
| 265 |
-
- `opened_at` (DATETIME, NULLABLE)
|
| 266 |
-
- `created_at` (DATETIME)
|
| 267 |
-
|
| 268 |
-
## Environment Variables
|
| 269 |
-
|
| 270 |
-
```env
|
| 271 |
-
DB_HOST=localhost
|
| 272 |
-
DB_PORT=3306
|
| 273 |
-
DB_USER=root
|
| 274 |
-
DB_PASS=
|
| 275 |
-
DB_NAME=moodlink
|
| 276 |
-
PORT=3000
|
| 277 |
-
|
| 278 |
-
# Firebase Configuration (optional)
|
| 279 |
-
FIREBASE_SERVICE_ACCOUNT_PATH=path/to/firebase-service-account.json
|
| 280 |
-
|
| 281 |
-
# Google Gemini API Configuration
|
| 282 |
-
GEMINI_API_KEY=your_gemini_api_key_here
|
| 283 |
-
```
|
| 284 |
-
|
| 285 |
-
## Achievements System
|
| 286 |
-
|
| 287 |
-
Available achievements:
|
| 288 |
-
- **First Step** 🌟: Complete first check-in
|
| 289 |
-
- **Streak 7 Hari** 🔥: Check-in for 7 consecutive days
|
| 290 |
-
- **Supporter** ❤️: Give 10 support reactions
|
| 291 |
-
- **Emotional Explorer** 🌈: Experience 5 different moods in 7 days
|
| 292 |
-
- **Level Master** 👑: Reach level 5
|
| 293 |
-
|
| 294 |
-
## Push Notifications
|
| 295 |
-
|
| 296 |
-
The system supports Firebase Cloud Messaging (FCM) for push notifications:
|
| 297 |
-
- Support received notifications
|
| 298 |
-
- Inactivity reminders (24h after last check-in)
|
| 299 |
-
- Custom admin notifications
|
| 300 |
-
- Configurable via Firebase service account
|
| 301 |
-
|
| 302 |
-
## Content Moderation
|
| 303 |
-
|
| 304 |
-
Automated content filtering using configurable terms in `moderation/words.txt`:
|
| 305 |
-
- Real-time content scanning during check-in
|
| 306 |
-
- Flagged content marked in database
|
| 307 |
-
- Admin interface for reviewing flagged content
|
| 308 |
-
- Regex-based pattern matching
|
| 309 |
-
|
| 310 |
-
## Rate Limiting
|
| 311 |
-
|
| 312 |
-
The following endpoints are rate-limited to 5 requests per user per minute:
|
| 313 |
-
- `POST /api/v1/checkin`
|
| 314 |
-
- `POST /api/v1/support`
|
| 315 |
-
- `POST /api/v1/comment`
|
| 316 |
-
- `POST /api/v1/chat/:room_id/message`
|
| 317 |
-
- `POST /api/v1/ai/reflect`
|
| 318 |
-
- `POST /api/v1/mood-mission/complete`
|
| 319 |
-
- `POST /api/v1/journal/future`
|
| 320 |
-
- `POST /api/v1/story/submit`
|
| 321 |
-
|
| 322 |
-
Rate limiting is based on the `User-ID` header.
|
| 323 |
-
|
| 324 |
-
## Points System
|
| 325 |
-
|
| 326 |
-
- **Check-in**: +10 points
|
| 327 |
-
- **Streak bonus**: +20 points (for consecutive days)
|
| 328 |
-
- **Sending support**: +2 points
|
| 329 |
-
- **Receiving support**: +5 points
|
| 330 |
-
- **Adding comment**: +3 points
|
| 331 |
-
- **Receiving comment**: +2 points
|
| 332 |
-
- **Chat message**: +1 point
|
| 333 |
-
- **AI reflection**: +5 points
|
| 334 |
-
- **Story submission**: +10 points
|
| 335 |
-
- **Mission completion**: +15 points
|
| 336 |
-
- **Capsule creation**: +5 points
|
| 337 |
-
- **Capsule opening**: +3 points
|
| 338 |
-
|
| 339 |
-
## Level System
|
| 340 |
-
|
| 341 |
-
- Level 1: < 100 points
|
| 342 |
-
- Level 2: 100-299 points
|
| 343 |
-
- Level 3: 300-699 points
|
| 344 |
-
- Level 4: 700-1499 points
|
| 345 |
-
- Level 5+: 1500+ points
|
| 346 |
-
|
| 347 |
-
## New Features
|
| 348 |
-
|
| 349 |
-
### User Customization
|
| 350 |
-
- Anonymous display names and avatar selection
|
| 351 |
-
- Theme customization (light/dark, color tones)
|
| 352 |
-
- Profile personalization while maintaining anonymity
|
| 353 |
-
|
| 354 |
-
### Bookmarking System
|
| 355 |
-
- Save inspiring journal entries from other users
|
| 356 |
-
- Personal bookmark collection with easy access
|
| 357 |
-
- Bookmark management and organization
|
| 358 |
-
|
| 359 |
-
### Leaderboard
|
| 360 |
-
- View top users by level, points, or streak
|
| 361 |
-
- Anonymous competition and motivation
|
| 362 |
-
- Encourages engagement and consistency
|
| 363 |
-
|
| 364 |
-
### Data Export
|
| 365 |
-
- Complete user data export in JSON format
|
| 366 |
-
- Includes all journal entries, achievements, and reflections
|
| 367 |
-
- Privacy-compliant data portability
|
| 368 |
-
|
| 369 |
-
### Streak Recovery
|
| 370 |
-
- Use points (50) to recover broken streaks
|
| 371 |
-
- Gamification element for streak maintenance
|
| 372 |
-
- Optional feature for dedicated users
|
| 373 |
-
|
| 374 |
-
### Enhanced Tagging
|
| 375 |
-
- Tag journal entries for better organization
|
| 376 |
-
- Trending tags discovery
|
| 377 |
-
- Improved search and filtering capabilities
|
| 378 |
-
|
| 379 |
-
## Google Auth Integration
|
| 380 |
-
|
| 381 |
-
Optional Google account binding allows users to:
|
| 382 |
-
- Link their anonymous UUID to Google account
|
| 383 |
-
- Restore their UUID after app reinstall
|
| 384 |
-
- Maintain data continuity across devices
|
| 385 |
-
|
| 386 |
-
### Link Google Account
|
| 387 |
-
```bash
|
| 388 |
-
curl -X POST http://localhost:3000/api/v1/auth/google \
|
| 389 |
-
-H "Content-Type: application/json" \
|
| 390 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 391 |
-
-d '{
|
| 392 |
-
"id_token": "google_id_token_here"
|
| 393 |
-
}'
|
| 394 |
-
```
|
| 395 |
-
|
| 396 |
-
### Restore Account
|
| 397 |
-
```bash
|
| 398 |
-
curl -X POST http://localhost:3000/api/v1/auth/restore \
|
| 399 |
-
-H "Content-Type: application/json" \
|
| 400 |
-
-d '{
|
| 401 |
-
"id_token": "google_id_token_here"
|
| 402 |
-
}'
|
| 403 |
-
```
|
| 404 |
-
|
| 405 |
-
## Usage
|
| 406 |
-
|
| 407 |
-
1. Set up MySQL database
|
| 408 |
-
2. Copy `.env.example` to `.env` and configure
|
| 409 |
-
3. (Optional) Set up Firebase project and download service account JSON
|
| 410 |
-
3. Run `go mod download` to install dependencies
|
| 411 |
-
4. Run `go run main.go` to start the server
|
| 412 |
-
|
| 413 |
-
## WebSocket Usage
|
| 414 |
-
|
| 415 |
-
Connect to `/ws/feed?user_id=<uuid>` to receive realtime updates.
|
| 416 |
-
|
| 417 |
-
### Message Types
|
| 418 |
-
|
| 419 |
-
**New Entry Broadcast:**
|
| 420 |
-
```json
|
| 421 |
-
{
|
| 422 |
-
"type": "new_entry",
|
| 423 |
-
"data": {
|
| 424 |
-
"id": "uuid",
|
| 425 |
-
"mood": "happy",
|
| 426 |
-
"note": "Feeling great today!",
|
| 427 |
-
"created_at": "2024-01-01T12:00:00Z",
|
| 428 |
-
"support_count": 0
|
| 429 |
-
}
|
| 430 |
-
}
|
| 431 |
-
```
|
| 432 |
-
|
| 433 |
-
**Support Notification (targeted to specific user):**
|
| 434 |
-
```json
|
| 435 |
-
{
|
| 436 |
-
"type": "support_received",
|
| 437 |
-
"data": {
|
| 438 |
-
"journal_id": "uuid",
|
| 439 |
-
"support": "heart"
|
| 440 |
-
}
|
| 441 |
-
}
|
| 442 |
-
```
|
| 443 |
-
|
| 444 |
-
## API Examples
|
| 445 |
-
|
| 446 |
-
### Register New User
|
| 447 |
-
```bash
|
| 448 |
-
curl -X POST http://localhost:3000/api/v1/user/register
|
| 449 |
-
```
|
| 450 |
-
|
| 451 |
-
### Get Today's Check-in Status
|
| 452 |
-
```bash
|
| 453 |
-
curl -H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 454 |
-
http://localhost:3000/api/v1/checkin/today
|
| 455 |
-
```
|
| 456 |
-
|
| 457 |
-
### Check-in
|
| 458 |
-
```bash
|
| 459 |
-
curl -X POST http://localhost:3000/api/v1/checkin \
|
| 460 |
-
-H "Content-Type: application/json" \
|
| 461 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 462 |
-
-d '{
|
| 463 |
-
"mood": "happy",
|
| 464 |
-
"note": "Had a great day at work!",
|
| 465 |
-
"tags": "[\"work\", \"productivity\", \"success\"]",
|
| 466 |
-
"location_lat": 40.7128,
|
| 467 |
-
"location_lng": -74.0060
|
| 468 |
-
}'
|
| 469 |
-
```
|
| 470 |
-
|
| 471 |
-
### Bookmark Journal Entry
|
| 472 |
-
```bash
|
| 473 |
-
curl -X POST http://localhost:3000/api/v1/bookmark \
|
| 474 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 475 |
-
-d '{"journal_id": "journal-uuid-here"}'
|
| 476 |
-
```
|
| 477 |
-
|
| 478 |
-
### Get Leaderboard
|
| 479 |
-
```bash
|
| 480 |
-
curl "http://localhost:3000/api/v1/leaderboard?by=level&limit=10"
|
| 481 |
-
```
|
| 482 |
-
|
| 483 |
-
### Update Profile
|
| 484 |
-
```bash
|
| 485 |
-
curl -X PATCH http://localhost:3000/api/v1/user/profile \
|
| 486 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 487 |
-
-d '{
|
| 488 |
-
"display_name": "Happy Explorer",
|
| 489 |
-
"avatar_type": "emoji_smile",
|
| 490 |
-
"theme": "dark",
|
| 491 |
-
"color_tone": "purple"
|
| 492 |
-
}'
|
| 493 |
-
```
|
| 494 |
-
|
| 495 |
-
### Export User Data
|
| 496 |
-
```bash
|
| 497 |
-
curl -H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 498 |
-
http://localhost:3000/api/v1/user/export
|
| 499 |
-
```
|
| 500 |
-
|
| 501 |
-
### Recover Streak
|
| 502 |
-
```bash
|
| 503 |
-
curl -X POST http://localhost:3000/api/v1/streak/recover \
|
| 504 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000"
|
| 505 |
-
```
|
| 506 |
-
|
| 507 |
-
### Send Support
|
| 508 |
-
```bash
|
| 509 |
-
curl -X POST http://localhost:3000/api/v1/support \
|
| 510 |
-
-H "Content-Type: application/json" \
|
| 511 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 512 |
-
-d '{
|
| 513 |
-
"journal_id": "550e8400-e29b-41d4-a716-446655440001",
|
| 514 |
-
"type": "heart"
|
| 515 |
-
}'
|
| 516 |
-
```
|
| 517 |
-
|
| 518 |
-
### Location-Based Feed
|
| 519 |
-
```bash
|
| 520 |
-
curl "http://localhost:3000/api/v1/feed?lat=40.7128&lng=-74.0060&radius_km=10"
|
| 521 |
-
```
|
| 522 |
-
|
| 523 |
-
### Report Journal Entry
|
| 524 |
-
```bash
|
| 525 |
-
curl -X POST http://localhost:3000/api/v1/report \
|
| 526 |
-
-H "Content-Type: application/json" \
|
| 527 |
-
-d '{
|
| 528 |
-
"journal_id": "550e8400-e29b-41d4-a716-446655440001",
|
| 529 |
-
"reason": "inappropriate content"
|
| 530 |
-
}'
|
| 531 |
-
```
|
| 532 |
-
|
| 533 |
-
### Global Statistics
|
| 534 |
-
```bash
|
| 535 |
-
curl http://localhost:3000/api/v1/stats/global
|
| 536 |
-
```
|
| 537 |
-
|
| 538 |
-
### Register Device Token
|
| 539 |
-
```bash
|
| 540 |
-
curl -X POST http://localhost:3000/api/v1/device-token \
|
| 541 |
-
-H "Content-Type: application/json" \
|
| 542 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 543 |
-
-d '{
|
| 544 |
-
"token": "fcm_device_token_here"
|
| 545 |
-
}'
|
| 546 |
-
```
|
| 547 |
-
|
| 548 |
-
### Get User Statistics
|
| 549 |
-
```bash
|
| 550 |
-
curl -H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 551 |
-
http://localhost:3000/api/v1/user/stats
|
| 552 |
-
```
|
| 553 |
-
|
| 554 |
-
### Reset Account
|
| 555 |
-
```bash
|
| 556 |
-
curl -X POST http://localhost:3000/api/v1/user/reset \
|
| 557 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000"
|
| 558 |
-
```
|
| 559 |
-
|
| 560 |
-
### Add Comment
|
| 561 |
-
```bash
|
| 562 |
-
curl -X POST http://localhost:3000/api/v1/comment \
|
| 563 |
-
-H "Content-Type: application/json" \
|
| 564 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 565 |
-
-d '{
|
| 566 |
-
"journal_id": "550e8400-e29b-41d4-a716-446655440001",
|
| 567 |
-
"comment": "Thanks for sharing this!"
|
| 568 |
-
}'
|
| 569 |
-
```
|
| 570 |
-
|
| 571 |
-
### Start Anonymous Chat
|
| 572 |
-
```bash
|
| 573 |
-
curl -X POST http://localhost:3000/api/v1/chat/start \
|
| 574 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000"
|
| 575 |
-
```
|
| 576 |
-
|
| 577 |
-
### Send Chat Message
|
| 578 |
-
```bash
|
| 579 |
-
curl -X POST http://localhost:3000/api/v1/chat/room-uuid/message \
|
| 580 |
-
-H "Content-Type: application/json" \
|
| 581 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 582 |
-
-d '{
|
| 583 |
-
"message": "Hello there!"
|
| 584 |
-
}'
|
| 585 |
-
```
|
| 586 |
-
|
| 587 |
-
### AI Reflection
|
| 588 |
-
```bash
|
| 589 |
-
curl -X POST http://localhost:3000/api/v1/ai/reflect \
|
| 590 |
-
-H "Content-Type: application/json" \
|
| 591 |
-
-H "User-ID: 550e8400-e29b-41d4-a716-446655440000" \
|
| 592 |
-
-d '{
|
| 593 |
-
"prompt": "I am feeling anxious about work today. How can I manage this feeling?"
|
| 594 |
-
}'
|
| 595 |
-
```
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: MoodLink Go Fiber
|
| 3 |
+
emoji: 🧠
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: blue
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_file: Dockerfile
|
| 8 |
+
pinned: false
|
| 9 |
+
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main.go
CHANGED
|
@@ -15,7 +15,7 @@ import (
|
|
| 15 |
)
|
| 16 |
|
| 17 |
func main() {
|
| 18 |
-
// Load environment
|
| 19 |
if err := godotenv.Load(); err != nil {
|
| 20 |
log.Println("No .env file found")
|
| 21 |
}
|
|
@@ -74,7 +74,7 @@ func main() {
|
|
| 74 |
// Start server
|
| 75 |
port := os.Getenv("PORT")
|
| 76 |
if port == "" {
|
| 77 |
-
port = "
|
| 78 |
}
|
| 79 |
|
| 80 |
log.Printf("Server starting on port %s", port)
|
|
|
|
| 15 |
)
|
| 16 |
|
| 17 |
func main() {
|
| 18 |
+
// Load environment variable
|
| 19 |
if err := godotenv.Load(); err != nil {
|
| 20 |
log.Println("No .env file found")
|
| 21 |
}
|
|
|
|
| 74 |
// Start server
|
| 75 |
port := os.Getenv("PORT")
|
| 76 |
if port == "" {
|
| 77 |
+
port = "7860"
|
| 78 |
}
|
| 79 |
|
| 80 |
log.Printf("Server starting on port %s", port)
|