matrix-pretix/internal/pretix/server.go

108 lines
1.8 KiB
Go

package pretix
import (
"context"
"database/sql"
"fmt"
"io"
"log"
"net/http"
"strings"
"sync"
"git.luj0ga.de/franconian/matrix-pretix/internal/config"
"git.luj0ga.de/franconian/matrix-pretix/internal/matrix"
)
type Server struct {
client http.Client
config *config.ServerConfig
db *sql.DB
matrix *matrix.Client
}
func NewServer(config *config.ServerConfig, db *sql.DB, matrix *matrix.Client) *Server {
return &Server{
config: config,
db: db,
matrix: matrix,
}
}
func (s Server) ListenAndServe(ctx context.Context, wg *sync.WaitGroup) error {
err := s.createTables()
if err != nil {
return err
}
http.HandleFunc("/", http.NotFound)
http.HandleFunc("/order_placed", s.orderPlaced)
server := http.Server{
Addr: s.config.ListenAddress,
}
go func() {
wg.Add(1)
defer wg.Done()
<-ctx.Done()
err := server.Shutdown(context.Background())
if err != nil {
log.Print(err)
}
}()
log.Print("listening on ", s.config.ListenAddress)
err = server.ListenAndServe()
if err != http.ErrServerClosed {
return err
}
return nil
}
func (s Server) createTables() error {
tables := []string{
`CREATE TABLE IF NOT EXISTS orders (
code TEXT PRIMARY KEY ON CONFLICT IGNORE
);
`,
}
tx, err := s.db.Begin()
if err != nil {
return err
}
for _, table := range tables {
_, err := tx.Exec(table)
if err != nil {
if err := tx.Rollback(); err != nil {
log.Print(err)
}
return err
}
}
err = tx.Commit()
if err != nil {
return err
}
return nil
}
func (s Server) buildURL(endpoint string, args ...any) string {
baseURL := strings.TrimSuffix(s.config.BaseURL, "/")
return fmt.Sprintf(endpoint, append([]any{baseURL}, args...)...)
}
func writeStatus(w http.ResponseWriter, code int) {
w.WriteHeader(code)
io.WriteString(w, http.StatusText(code))
}