sojorn/go-backend/internal/config/config.go
Patrick Britton 38653f5854 Sojorn Backend Finalization & Cleanup - Complete Migration from Supabase
##  Phase 1: Critical Feature Completion (Beacon Voting)
- Add VouchBeacon, ReportBeacon, RemoveBeaconVote methods to PostRepository
- Implement beacon voting HTTP handlers with confidence score calculations
- Register new beacon routes: /beacons/:id/vouch, /beacons/:id/report, /beacons/:id/vouch (DELETE)
- Auto-flag beacons at 5+ reports, confidence scoring (0.5 base + 0.1 per vouch)

##  Phase 2: Feed Logic & Post Distribution Integrity
- Verify unified feed logic supports all content types (Standard, Quips, Beacons)
- Ensure proper distribution: Profile Feed + Main/Home Feed for followers
- Beacon Map integration for location-based content
- Video content filtering for Quips feed

##  Phase 3: The Notification System
- Create comprehensive NotificationService with FCM integration
- Add CreateNotification method to NotificationRepository
- Implement smart deep linking: beacon_map, quip_feed, main_feed
- Trigger notifications for beacon interactions and cross-post comments
- Push notification logic with proper content type detection

##  Phase 4: The Great Supabase Purge
- Delete function_proxy.go and remove /functions/:name route
- Remove SupabaseURL, SupabaseKey from config.go
- Remove SupabaseID field from User model
- Clean all Supabase imports and dependencies
- Sanitize codebase of legacy Supabase references

##  Phase 5: Flutter Frontend Integration
- Implement vouchBeacon(), reportBeacon(), removeBeaconVote() in ApiService
- Replace TODO delay in video_comments_sheet.dart with actual publishComment call
- Fix compilation errors (named parameters, orphaned child properties)
- Complete frontend integration with Go API endpoints

##  Additional Improvements
- Fix compilation errors in threaded_comment_widget.dart (orphaned child property)
- Update video_comments_sheet.dart to use proper named parameters
- Comprehensive error handling and validation
- Production-ready notification system with deep linking

##  Migration Status: 100% Complete
- Backend: Fully migrated from Supabase to custom Go/Gin API
- Frontend: Integrated with new Go endpoints
- Notifications: Complete FCM integration with smart routing
- Database: Clean of all Supabase dependencies
- Features: All functionality preserved and enhanced

Ready for VPS deployment and production testing!
2026-01-30 09:24:31 -06:00

96 lines
3.1 KiB
Go

package config
import (
"os"
"strconv"
"github.com/joho/godotenv"
)
type Config struct {
Port string
Env string
LogLevel string
DatabaseURL string
JWTSecret string
CORSOrigins string
RateLimitRPS int
SMTPHost string
SMTPPort int
SMTPUser string
SMTPPass string
SMTPFrom string
SenderAPIToken string
SendPulseID string
SendPulseSecret string
R2SigningSecret string
R2PublicBaseURL string
FirebaseCredentialsFile string
R2AccountID string
R2APIToken string
R2ImgDomain string
R2VidDomain string
R2Endpoint string
R2AccessKey string
R2SecretKey string
R2MediaBucket string
R2VideoBucket string
}
func LoadConfig() *Config {
// Try current directory first
err := godotenv.Load()
if err != nil {
// Try parent directory (common for VPS structure /opt/sojorn/.env while binary is in /opt/sojorn/go-backend)
_ = godotenv.Load("../.env")
// Try absolute path specified by user
_ = godotenv.Load("/opt/sojorn/.env")
}
return &Config{
Port: getEnv("PORT", "8080"),
Env: getEnv("ENV", "development"),
LogLevel: getEnv("LOG_LEVEL", "info"),
DatabaseURL: getEnv("DATABASE_URL", ""),
JWTSecret: getEnv("JWT_SECRET", ""),
CORSOrigins: getEnv("CORS_ORIGINS", "*"),
RateLimitRPS: getEnvInt("RATE_LIMIT_RPS", 10),
SMTPHost: getEnv("SMTP_HOST", "smtp.sender.net"),
SMTPPort: getEnvInt("SMTP_PORT", 587),
SMTPUser: getEnv("SMTP_USER", ""),
SMTPPass: getEnv("SMTP_PASS", ""),
SMTPFrom: getEnv("SMTP_FROM", "no-reply@gosojorn.com"),
SenderAPIToken: getEnv("SENDER_API_TOKEN", ""),
SendPulseID: getEnv("SENDPULSE_ID", ""),
SendPulseSecret: getEnv("SENDPULSE_SECRET", ""),
R2SigningSecret: getEnv("R2_SIGNING_SECRET", ""),
// Default to the public CDN domain to avoid mixed-content/http defaults.
R2PublicBaseURL: getEnv("R2_PUBLIC_BASE_URL", "https://img.gosojorn.com"),
FirebaseCredentialsFile: getEnv("FIREBASE_CREDENTIALS_FILE", "firebase-service-account.json"),
R2AccountID: getEnv("R2_ACCOUNT_ID", ""),
R2APIToken: getEnv("R2_API_TOKEN", ""),
R2ImgDomain: getEnv("R2_IMG_DOMAIN", "img.gosojorn.com"),
R2VidDomain: getEnv("R2_VID_DOMAIN", "quips.gosojorn.com"),
R2Endpoint: getEnv("R2_ENDPOINT", ""),
R2AccessKey: getEnv("R2_ACCESS_KEY", ""),
R2SecretKey: getEnv("R2_SECRET_KEY", ""),
R2MediaBucket: getEnv("R2_MEDIA_BUCKET", "sojorn-media"),
R2VideoBucket: getEnv("R2_VIDEO_BUCKET", "sojorn-videos"),
}
}
func getEnv(key, fallback string) string {
if value, exists := os.LookupEnv(key); exists {
return value
}
return fallback
}
func getEnvInt(key string, fallback int) int {
valueStr := getEnv(key, "")
if value, err := strconv.Atoi(valueStr); err == nil {
return value
}
return fallback
}