照慣例,先上spec
/googleCalendar/getGoogleCalendarEventList/{calendarId}:
get:
summary: Get a list of events from Google Calendar
parameters:
- name: calendarId
in: path
required: true
description: ID of the Google Calendar to retrieve events from
schema:
type: string
- name: timeMin
in: query
required: false
description: Lower bound (exclusive) for an event's end time to filter by.
schema:
type: string
- name: timeMax
in: query
required: false
description: Upper bound (exclusive) for an event's start time to filter by
schema:
type: string
responses:
'200':
description: List of events from Google Calendar
'404':
description: Calendar not found
難得今天用的是GET🤪
func main() {
r := gin.Default()
c := controller.NewController()
v1 := r.Group("/api/v1")
{
googleCalendar := v1.Group("/googleCalendar")
{
googleCalendar.GET("/getEventList/:calendarId", c.GetGoogleCalendarEventList)
}
...
這邊跟原本的內容差不多,就只是加上path中有calendarId
這邊的改動有點多,所以我也是先一段一段講
// GetGoogleCalendarEventList godoc
//
// @Summary Get Google Calendar Event List
// @Description Get a list of events from Google Calendar
// @Tags googleCalendar
// @Accept json
// @Produce json
// @Param calendarId path string true "Database ID"
// @Param timeMin query string false "timeMin"
// @Param timeMax query string false "timeMax"
// @Success 200 {array} responseModel.CalendarEvents "success"
// @Failure 400 {string} string "fail"
// @Failure 404 {string} string "Calendar not found"
// @Router /api/v1/googleCalendar/getEventList/{calendarId} [get]
先從swaggo的內容開始講起,跟前面不同的是這邊多個兩個query
這兩個query主要是用來限制google calendar搜尋的內容
因為後續sync的時候,目前的規劃是只會sync一天的內容
以防要比對太多東西運算量有點大,在notion的地方有filter可以用
而在google calendar這邊就要用timeMax跟timeMin來限制區間
func (c *Controller) GetGoogleCalendarEventList(ctx *gin.Context) {
configHandler := util.NewConfigHandler()
auth := configHandler.GetSecretConfig().Get("GoogleSecretKey")
calendarId := ctx.Param("calendarId")
calendarService, err := calendar.NewService(ctx, option.WithAPIKey(auth.(string)))
if err != nil {
panic(err)
}
...
code一開始的改動只有增加讀取calendarId這個參數
func (c *Controller) GetGoogleCalendarEventList(ctx *gin.Context) {
...
timeMin := ctx.Request.URL.Query().Get("timeMin")
checkTimeFormat(timeMin, "Error parsing timeMin:", ctx)
timeMax := ctx.Request.URL.Query().Get("timeMax")
checkTimeFormat(timeMax, "Error parsing timeMax:", ctx)
...
}
func checkTimeFormat(timeStr string, errMsg string, ctx *gin.Context) {
if timeStr != "" {
_, err := time.Parse("2006-01-02T15:04:05+00:00", timeStr)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{errMsg: err.Error()})
}
}
}
由於讓上面的時間用string的方式來讀取,所以這邊透過一個checkTimeFormat來確定這兩個時間的內容format是正常的,如果有值才會確定是不是正常的
func (c *Controller) GetGoogleCalendarEventList(ctx *gin.Context) {
...
eventList := &calendar.Events{}
switch {
case timeMin != "" && timeMax != "":
eventList, err = calendarService.Events.List(calendarId).TimeMin(timeMin).TimeMax(timeMax).Do()
case timeMax != "":
eventList, err = calendarService.Events.List(calendarId).TimeMax(timeMax).Do()
case timeMin != "":
eventList, err = calendarService.Events.List(calendarId).TimeMin(timeMin).Do()
default:
eventList, err = calendarService.Events.List(calendarId).Do()
}
if err != nil {
panic(err)
}
...
}
接著用一個switch來確定有沒有timeMin或timeMax的值,有的話才要使用這個function,沒有的話用了會跳500 error
func (c *Controller) GetGoogleCalendarEventList(ctx *gin.Context) {
...
var response responseModel.CalendarEvents
response.Kind = eventList.Kind
response.Etag = eventList.Etag
response.Summary = eventList.Summary
response.Description = eventList.Description
response.Updated = eventList.Updated
response.TimeZone = eventList.TimeZone
response.AccessRole = eventList.AccessRole
response.NextSyncToken = eventList.NextSyncToken
for _, item := range eventList.Items {
response.Items = append(response.Items, responseModel.Event{
Kind: item.Kind,
Etag: item.Etag,
Id: item.Id,
Status: item.Status,
HtmlLink: item.HtmlLink,
Created: item.Created,
Updated: item.Updated,
Summary: item.Summary,
Creator: struct {
Email string `json:"email"`
}{
Email: item.Creator.Email,
},
Organizer: struct {
Email string `json:"email"`
DisplayName string `json:"displayName"`
Self bool `json:"self"`
}{
Email: item.Organizer.Email,
DisplayName: item.Organizer.DisplayName,
Self: item.Organizer.Self,
},
Start: struct {
DateTime string `json:"dateTime"`
TimeZone string `json:"timeZone"`
}{
DateTime: item.Start.DateTime,
TimeZone: item.Start.TimeZone,
},
End: struct {
DateTime string `json:"dateTime"`
TimeZone string `json:"timeZone"`
}{
DateTime: item.End.DateTime,
TimeZone: item.End.TimeZone,
},
ICalUID: item.ICalUID,
EventType: item.EventType,
})
}
ctx.JSON(http.StatusOK, eventList)
...
}
接著要把google calendar的內容接回來,這邊主要是要把calendar.Events的內容接到response的內容
package responseModel
type Event struct {
Kind string `json:"kind"`
Etag string `json:"etag"`
Id string `json:"id"`
Status string `json:"status"`
HtmlLink string `json:"htmlLink"`
Created string `json:"created"`
Updated string `json:"updated"`
Summary string `json:"summary"`
Creator struct {
Email string `json:"email"`
} `json:"creator"`
Organizer struct {
Email string `json:"email"`
DisplayName string `json:"displayName"`
Self bool `json:"self"`
} `json:"organizer"`
Start struct {
DateTime string `json:"dateTime"`
TimeZone string `json:"timeZone"`
} `json:"start"`
End struct {
DateTime string `json:"dateTime"`
TimeZone string `json:"timeZone"`
} `json:"end"`
ICalUID string `json:"iCalUID"`
Sequence int `json:"sequence"`
EventType string `json:"eventType"`
}
type CalendarEvents struct {
Kind string `json:"kind"`
Etag string `json:"etag"`
Summary string `json:"summary"`
Description string `json:"description"`
Updated string `json:"updated"`
TimeZone string `json:"timeZone"`
AccessRole string `json:"accessRole"`
DefaultReminders []struct{} `json:"defaultReminders"`
NextSyncToken string `json:"nextSyncToken"`
Items []Event `json:"items"`
}
這邊也是根據google calendar打回來的內容,將json轉成golang的struct
#!/bin/bash
export PATH="$PATH:$(go env GOPATH)/bin"
export GO111MODULE=on
# rm -f -r ../assets/swagger/docs
rm -f -r ./docs/swagger/docs
# go get -u github.com/swaggo/swag/cmd/swag
go mod download
swag init -o ./docs/swagger/docs --ot json,yaml
echo "Suceessfully generated swagger docs."
在update-swagger的時候有時候會說找不到swag,所以這邊加了兩行處理golang變數的內容
如果有出現一樣的錯誤可以參考
今天就先不demo了,明天要開始串接這幾隻api
主要是先打google calendar list,再打query notion db
這兩隻api的區間都設定在當天00:00:00到當前的時間
然後比對event的內容,如果有少的,就用create notion page來新增項目到notion db中