fix: resolve cyclop, funlen issues by extracting helper methods
This commit is contained in:
@@ -662,63 +662,52 @@ func (s *Database) applyMigrations(
|
||||
migrations []migration,
|
||||
) error {
|
||||
for _, m := range migrations {
|
||||
var exists int
|
||||
|
||||
err := s.db.QueryRowContext(ctx,
|
||||
"SELECT COUNT(*) FROM schema_migrations WHERE version = ?",
|
||||
m.version,
|
||||
).Scan(&exists)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"check migration %d: %w", m.version, err,
|
||||
)
|
||||
}
|
||||
|
||||
if exists > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
s.log.Info(
|
||||
"applying migration",
|
||||
"version", m.version, "name", m.name,
|
||||
)
|
||||
|
||||
tx, err := s.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"begin tx for migration %d: %w", m.version, err,
|
||||
)
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, m.sql)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
|
||||
return fmt.Errorf(
|
||||
"apply migration %d (%s): %w",
|
||||
m.version, m.name, err,
|
||||
)
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx,
|
||||
"INSERT INTO schema_migrations (version) VALUES (?)",
|
||||
m.version,
|
||||
)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
|
||||
return fmt.Errorf(
|
||||
"record migration %d: %w", m.version, err,
|
||||
)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"commit migration %d: %w", m.version, err,
|
||||
)
|
||||
if err := s.applyOneMigration(ctx, m); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Database) applyOneMigration(ctx context.Context, m migration) error {
|
||||
var exists int
|
||||
|
||||
err := s.db.QueryRowContext(ctx,
|
||||
"SELECT COUNT(*) FROM schema_migrations WHERE version = ?",
|
||||
m.version,
|
||||
).Scan(&exists)
|
||||
if err != nil {
|
||||
return fmt.Errorf("check migration %d: %w", m.version, err)
|
||||
}
|
||||
|
||||
if exists > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
s.log.Info("applying migration", "version", m.version, "name", m.name)
|
||||
|
||||
tx, err := s.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("begin tx for migration %d: %w", m.version, err)
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, m.sql)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
|
||||
return fmt.Errorf("apply migration %d (%s): %w", m.version, m.name, err)
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx,
|
||||
"INSERT INTO schema_migrations (version) VALUES (?)",
|
||||
m.version,
|
||||
)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
|
||||
return fmt.Errorf("record migration %d: %w", m.version, err)
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
@@ -239,51 +239,53 @@ func (s *Handlers) HandleSendCommand() http.HandlerFunc {
|
||||
|
||||
req.Command = strings.ToUpper(strings.TrimSpace(req.Command))
|
||||
req.To = strings.TrimSpace(req.To)
|
||||
lines := extractBodyLines(req.Body)
|
||||
|
||||
// Helper to extract body as string lines.
|
||||
bodyLines := func() []string {
|
||||
switch v := req.Body.(type) {
|
||||
case []any:
|
||||
lines := make([]string, 0, len(v))
|
||||
s.dispatchCommand(w, r, uid, nick, req.Command, req.To, lines)
|
||||
}
|
||||
}
|
||||
|
||||
for _, item := range v {
|
||||
if str, ok := item.(string); ok {
|
||||
lines = append(lines, str)
|
||||
}
|
||||
}
|
||||
// extractBodyLines converts the request body to string lines.
|
||||
func extractBodyLines(body any) []string {
|
||||
switch v := body.(type) {
|
||||
case []any:
|
||||
lines := make([]string, 0, len(v))
|
||||
|
||||
return lines
|
||||
case []string:
|
||||
return v
|
||||
default:
|
||||
return nil
|
||||
for _, item := range v {
|
||||
if str, ok := item.(string); ok {
|
||||
lines = append(lines, str)
|
||||
}
|
||||
}
|
||||
|
||||
switch req.Command {
|
||||
case "PRIVMSG", "NOTICE":
|
||||
s.handlePrivmsg(w, r, uid, nick, req.To, bodyLines())
|
||||
return lines
|
||||
case []string:
|
||||
return v
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
case "JOIN":
|
||||
s.handleJoin(w, r, uid, req.To)
|
||||
func (s *Handlers) dispatchCommand(
|
||||
w http.ResponseWriter, r *http.Request,
|
||||
uid, nick, command, to string, lines []string,
|
||||
) {
|
||||
switch command {
|
||||
case "PRIVMSG", "NOTICE":
|
||||
s.handlePrivmsg(w, r, uid, nick, to, lines)
|
||||
case "JOIN":
|
||||
s.handleJoin(w, r, uid, to)
|
||||
case "PART":
|
||||
s.handlePart(w, r, uid, to)
|
||||
case "NICK":
|
||||
s.handleNick(w, r, uid, lines)
|
||||
case "TOPIC":
|
||||
s.handleTopic(w, r, uid, to, lines)
|
||||
case "PING":
|
||||
s.respondJSON(w, r, map[string]string{"command": "PONG", "from": s.params.Config.ServerName}, http.StatusOK)
|
||||
default:
|
||||
_ = nick
|
||||
|
||||
case "PART":
|
||||
s.handlePart(w, r, uid, req.To)
|
||||
|
||||
case "NICK":
|
||||
s.handleNick(w, r, uid, bodyLines())
|
||||
|
||||
case "TOPIC":
|
||||
s.handleTopic(w, r, uid, req.To, bodyLines())
|
||||
|
||||
case "PING":
|
||||
s.respondJSON(w, r, map[string]string{"command": "PONG", "from": s.params.Config.ServerName}, http.StatusOK)
|
||||
|
||||
default:
|
||||
_ = nick // suppress unused warning
|
||||
|
||||
s.respondJSON(w, r, map[string]string{"error": "unknown command: " + req.Command}, http.StatusBadRequest)
|
||||
}
|
||||
s.respondJSON(w, r, map[string]string{"error": "unknown command: " + command}, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,34 +65,38 @@ func (s *Server) SetupRoutes() {
|
||||
r.Get("/channels/{channel}/members", s.h.HandleChannelMembers())
|
||||
})
|
||||
|
||||
// Serve embedded SPA
|
||||
s.setupSPA()
|
||||
}
|
||||
|
||||
func (s *Server) setupSPA() {
|
||||
distFS, err := fs.Sub(web.Dist, "dist")
|
||||
if err != nil {
|
||||
s.log.Error("failed to get web dist filesystem", "error", err)
|
||||
} else {
|
||||
fileServer := http.FileServer(http.FS(distFS))
|
||||
|
||||
s.router.Get("/*", func(w http.ResponseWriter, r *http.Request) {
|
||||
readFS, ok := distFS.(fs.ReadFileFS)
|
||||
if !ok {
|
||||
http.Error(w, "internal error", http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Try to serve the file; if not found, serve index.html for SPA routing
|
||||
f, err := readFS.ReadFile(r.URL.Path[1:])
|
||||
if err != nil || len(f) == 0 {
|
||||
indexHTML, _ := readFS.ReadFile("index.html")
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(indexHTML)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
fileServer.ServeHTTP(w, r)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
fileServer := http.FileServer(http.FS(distFS))
|
||||
|
||||
s.router.Get("/*", func(w http.ResponseWriter, r *http.Request) {
|
||||
readFS, ok := distFS.(fs.ReadFileFS)
|
||||
if !ok {
|
||||
http.Error(w, "internal error", http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
f, err := readFS.ReadFile(r.URL.Path[1:])
|
||||
if err != nil || len(f) == 0 {
|
||||
indexHTML, _ := readFS.ReadFile("index.html")
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(indexHTML)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
fileServer.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user