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)) }