diff --git a/.gitignore b/.gitignore index 583f327..0714a4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .env /go.mod -/go.sum \ No newline at end of file +/go.sum +logs/ +TodayOnHistory \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..0626f07 --- /dev/null +++ b/main.go @@ -0,0 +1,209 @@ +package main + +import ( + "database/sql" + "encoding/json" + "fmt" + "net/http" + "os" + "strconv" + "time" + + "code.akitsuki.me/AkitsukiNagi/logging" + _ "github.com/joho/godotenv/autoload" + _ "github.com/lib/pq" +) + +type Event struct { + Title string `json:"title"` + Description string `json:"description"` + Year int `json:"year"` +} + +type Response struct { + Year int `json:"year"` + Month int `json:"month"` + Day int `json:"day"` + Events []*Event `json:"events"` +} + +var ( + db *sql.DB + connStr = fmt.Sprintf( + "host=%s user=%s password=%s dbname=%s port=%s sslmode=%s", + os.Getenv("HOST"), + os.Getenv("USER"), + os.Getenv("PASSWORD"), + os.Getenv("DBNAME"), + os.Getenv("PORT"), + os.Getenv("SSLMODE"), + ) + loc *time.Location + port int + static = http.FileServer(http.Dir("./static")) +) + +func init() { + var err error + port, err = strconv.Atoi(os.Getenv("HTTP_PORT")) + if err != nil { + logging.GetLogger().Critical("Error parsing port: %v", err) + } +} + +func main() { + loc, _ = time.LoadLocation("Asia/Taipei") + + var err error + db, err = sql.Open("postgres", connStr) + if err != nil { + logging.GetLogger().Error("Failed to connect to the database: %v", err) + } + + err = db.Ping() + if err != nil { + logging.GetLogger().Error("Failed to ping to the database: %v", err) + } else { + logging.GetLogger().Info("Successfully connected to the database.") + } + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + static.ServeHTTP(w, r) + }) + + http.Handle("/static/", http.StripPrefix("/static", static)) + http.HandleFunc("/static/index.html", func(w http.ResponseWriter, r *http.Request) { + http.NotFound(w, r) + }) + + http.HandleFunc("/api/query", serveAPI) + + logging.GetLogger().Info("Server started on localhost:%d", port) + logging.GetLogger().Error("%v", http.ListenAndServe(fmt.Sprintf(":%d", port), nil)) +} + +func serveAPI(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + var ( + resp Response + events []*Event + date time.Time + + sYear = query.Get("year") + sMonth = query.Get("month") + sDay = query.Get("day") + ) + + if sYear == "" && sMonth == "" && sDay == "" { + date = time.Now() + events = apiQuerying(date.Year(), int(date.Month()), date.Day()) + resp = Response{ + Year: date.Year(), + Month: int(date.Month()), + Day: date.Day(), + Events: events, + } + + err := json.NewEncoder(w).Encode(resp) + if err != nil { + logging.GetLogger().Error("Failed to parse data into json: %v", err) + } + return + } + + year, month, day := parseTime(sYear, sMonth, sDay) + date = time.Now() + sDate := fmt.Sprintf("%d/%d/%d", year, month, day) + date, err := time.Parse("2006/1/2", sDate) + if err != nil { + logging.GetLogger().Error("Error parsing date: %v", err) + } + + events = apiQuerying(date.Year(), int(date.Month()), date.Day()) + resp = Response{ + Year: date.Year(), + Month: int(date.Month()), + Day: date.Day(), + Events: events, + } + + err = json.NewEncoder(w).Encode(resp) + if err != nil { + logging.GetLogger().Error("Failed to parse data into json: %v", err) + } +} + +func apiQuerying(year, month, day int) []*Event { + var ( + rows *sql.Rows + err error + ) + + rows, err = db.Query("SELECT year, title, description FROM events WHERE month = $1 AND day = $2 AND YEAR <= $3 ORDER BY year", month, day, year) + if err != nil { + logging.GetLogger().Error("%v", err) + } + + var events []*Event + + defer rows.Close() + for rows.Next() { + event := &Event{} + err := rows.Scan(&event.Year, &event.Title, &event.Description) + if err != nil { + logging.GetLogger().Error("%v", err) + } else { + events = append(events, event) + } + } + + return events +} + +func parseTime(sYear, sMonth, sDay string) (int, int, int) { + var ( + year int = 0 + month int = 0 + day int = 0 + err error + reset = false + + now = time.Now() + ) + + if sYear != "" { + year, err = strconv.Atoi(sYear) + if err != nil { + year = 0 + } + } + if sYear == "" || year == 0 { + reset = true + } + + if sMonth != "" { + month, err = strconv.Atoi(sMonth) + if err != nil { + month = 0 + } + } + if sMonth == "" || month == 0 { + reset = true + } + + if sDay != "" { + day, err = strconv.Atoi(sDay) + if err != nil { + day = 0 + } + } + if sDay == "" || day == 0 { + reset = true + } + + if reset { + year, month, day = now.Year(), int(now.Month()), now.Day() + } + + return year, month, day +} diff --git a/static/index.html b/static/index.html index 94966fc..184b135 100755 --- a/static/index.html +++ b/static/index.html @@ -7,19 +7,47 @@
正在載入歷史事件...