This repository was archived by the owner on Feb 17, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
125 lines (101 loc) · 3.14 KB
/
Copy pathmain.go
File metadata and controls
125 lines (101 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main
import (
"context"
"log/slog"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"github.com/shopwarelabs/discord-bot/handlers"
"github.com/shopwarelabs/discord-bot/models"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
)
func main() {
// Load .env file if it exists
_ = godotenv.Load()
// Load configuration
config := models.LoadConfig()
// Validate required configuration
if config.MicrosoftClientID == "" || config.MicrosoftClientSecret == "" ||
config.DiscordToken == "" || config.DiscordGuildID == "" || config.DiscordRoleID == "" {
slog.Error("Missing required configuration", "error", "Please check your environment variables")
}
// Ensure database directory exists
if err := os.MkdirAll(filepath.Dir(config.DatabasePath), 0755); err != nil {
slog.Error("Failed to create database directory", "error", err)
}
// Initialize database
db, err := models.NewDatabase(config.DatabasePath)
if err != nil {
slog.Error("Failed to initialize database", "error", err)
}
defer func() {
_ = db.Close()
}()
// Create verification store
store := models.NewVerificationStore(db)
// Initialize handlers
discordHandler, err := handlers.NewDiscordHandler(config, store)
if err != nil {
slog.Error("Failed to create Discord handler", "error", err)
}
oauthHandler, err := handlers.NewOAuthHandler(config, store, discordHandler)
if err != nil {
slog.Error("Failed to create OAuth handler", "error", err)
}
// Start Discord bot
if err := discordHandler.Start(); err != nil {
slog.Error("Failed to start Discord bot", "error", err)
}
defer func() {
_ = discordHandler.Stop()
}()
// Setup Gin router
router := gin.Default()
// Setup session store
sessionStore := cookie.NewStore([]byte(config.SessionSecret))
sessionStore.Options(sessions.Options{
Path: "/",
MaxAge: 3600, // 1 hour
HttpOnly: true,
Secure: false, // Set to true in production with HTTPS
SameSite: http.SameSiteLaxMode,
})
router.Use(sessions.Sessions("discord-session", sessionStore))
router.LoadHTMLGlob("templates/*")
router.GET("/employee/start", oauthHandler.StartAuth)
router.GET("/employee/callback", oauthHandler.Callback)
// Health check
router.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "healthy"})
})
// Create HTTP server
srv := &http.Server{
Addr: ":" + config.Port,
Handler: router,
}
// Start server in goroutine
go func() {
slog.Info("Starting web server on port", "port", config.Port)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
slog.Error("Failed to start server", "err", err)
}
}()
// Wait for interrupt signal to gracefully shutdown the server
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
slog.Info("Shutting down server...")
// Graceful shutdown with timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
slog.Error("Server forced to shutdown", "error", err)
}
slog.Info("Server exited")
}