Files
TodayOnHistory/main.go

210 lines
4.2 KiB
Go

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
}