2016-09-23 13:20:27 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-12-27 03:56:57 +00:00
|
|
|
_ "embed"
|
2016-09-23 13:20:27 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
2017-02-02 10:17:58 +00:00
|
|
|
"strings"
|
2016-09-23 13:20:27 +00:00
|
|
|
"time"
|
|
|
|
|
2018-09-09 21:27:55 +00:00
|
|
|
"github.com/Luzifer/go-holidays/holidays"
|
2021-02-19 18:02:46 +00:00
|
|
|
"github.com/Luzifer/rconfig/v2"
|
2021-12-27 03:56:57 +00:00
|
|
|
|
2016-09-23 13:20:27 +00:00
|
|
|
"github.com/gorilla/mux"
|
2021-12-27 03:56:57 +00:00
|
|
|
log "github.com/sirupsen/logrus"
|
2016-09-23 13:20:27 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
cfg = struct {
|
|
|
|
Listen string `flag:"listen" default:":3000" description:"IP/Port to listen on"`
|
|
|
|
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
|
|
|
|
}{}
|
|
|
|
|
2021-12-27 03:56:57 +00:00
|
|
|
//go:embed index.html
|
|
|
|
indexHTML []byte
|
|
|
|
|
2016-09-23 13:20:27 +00:00
|
|
|
version = "dev"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
if err := rconfig.Parse(&cfg); err != nil {
|
|
|
|
log.Fatalf("Unable to parse commandline options: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if cfg.VersionAndExit {
|
|
|
|
fmt.Printf("holiday-api %s\n", version)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
r := mux.NewRouter()
|
2021-12-27 03:56:57 +00:00
|
|
|
parts := []string{"", "{country-code:[a-z-]+}", "{year:[0-9]{4}}", "{month:[0-9]{2}}", "{day:[0-9]{2}}"}
|
|
|
|
for i := 2; i <= len(parts); i++ {
|
|
|
|
p := strings.Join(parts[:i], "/")
|
|
|
|
r.HandleFunc(p, handleHolidays)
|
|
|
|
r.HandleFunc(strings.Join([]string{p, "{format:[a-z]+}"}, "."), handleHolidays)
|
|
|
|
}
|
2017-02-02 02:37:43 +00:00
|
|
|
r.HandleFunc("/", handleReadme)
|
2017-02-02 10:28:37 +00:00
|
|
|
|
|
|
|
srv := &http.Server{
|
|
|
|
Addr: cfg.Listen,
|
|
|
|
Handler: r,
|
|
|
|
ReadTimeout: time.Second,
|
|
|
|
WriteTimeout: time.Second,
|
|
|
|
}
|
|
|
|
log.Println(srv.ListenAndServe())
|
2016-09-23 13:20:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func handleHolidays(res http.ResponseWriter, r *http.Request) {
|
|
|
|
vars := mux.Vars(r)
|
|
|
|
|
|
|
|
var (
|
|
|
|
countryCode = vars["country-code"]
|
2021-12-27 03:56:57 +00:00
|
|
|
format = vars["format"]
|
2021-12-27 04:04:34 +00:00
|
|
|
locale = r.FormValue("locale")
|
2016-09-23 13:20:27 +00:00
|
|
|
year = time.Now().Year()
|
|
|
|
)
|
|
|
|
|
2021-12-27 03:56:57 +00:00
|
|
|
if format == "" {
|
|
|
|
format = "json"
|
|
|
|
}
|
|
|
|
|
2016-09-23 13:20:27 +00:00
|
|
|
if y, ok := vars["year"]; ok {
|
|
|
|
var err error
|
|
|
|
if year, err = strconv.Atoi(y); err != nil {
|
|
|
|
http.Error(res, "You need to specify the year as a 4 character number", http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-02 10:17:58 +00:00
|
|
|
check := strings.TrimRight(strings.Join([]string{strconv.Itoa(year), vars["month"], vars["day"]}, "-"), "-")
|
|
|
|
|
|
|
|
days, err := holidays.GetHolidays(countryCode, year)
|
2016-09-23 13:20:27 +00:00
|
|
|
if err != nil {
|
|
|
|
http.Error(res, "An error ocurred: "+err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-02-02 10:17:58 +00:00
|
|
|
outputSet := []holidays.Holiday{}
|
|
|
|
for _, h := range days {
|
|
|
|
if strings.HasPrefix(h.Date, check) {
|
|
|
|
outputSet = append(outputSet, h)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-27 03:56:57 +00:00
|
|
|
switch format {
|
|
|
|
case "ics":
|
|
|
|
cal := iCalendar{}
|
|
|
|
for _, h := range outputSet {
|
2021-12-27 04:04:34 +00:00
|
|
|
name := h.Name
|
|
|
|
if h.LocalizedName != nil && h.LocalizedName[locale] != "" {
|
|
|
|
name = h.LocalizedName[locale]
|
|
|
|
}
|
|
|
|
|
2021-12-27 03:56:57 +00:00
|
|
|
cal.Events = append(cal.Events, iCalendarEvent{
|
2021-12-27 04:04:34 +00:00
|
|
|
Summary: name,
|
2021-12-27 03:56:57 +00:00
|
|
|
Date: h.ParsedDate,
|
|
|
|
UID: fmt.Sprintf("%s_%s@hoiday-api.fyi", countryCode, h.ParsedDate.Format("20060102")),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
res.Header().Set("Content-Type", "text/calendar")
|
|
|
|
fmt.Fprintln(res, cal.String())
|
|
|
|
|
|
|
|
case "json":
|
|
|
|
res.Header().Set("Content-Type", "application/json")
|
|
|
|
json.NewEncoder(res).Encode(outputSet)
|
|
|
|
|
|
|
|
default:
|
|
|
|
http.Error(res, fmt.Sprintf("Unknown format: %s", format), http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
2016-09-23 13:20:27 +00:00
|
|
|
}
|
2017-02-02 02:37:43 +00:00
|
|
|
|
|
|
|
func handleReadme(res http.ResponseWriter, r *http.Request) {
|
2021-12-27 03:56:57 +00:00
|
|
|
res.Write(indexHTML)
|
2017-02-02 02:37:43 +00:00
|
|
|
}
|