local M = {}
local oauth2 = require("assay.oauth2")
local GCAL_API = "https://www.googleapis.com"
local TOKEN_URL = "https://oauth2.googleapis.com/token"
function M.client(opts)
opts = opts or {}
local credentials_file = opts.credentials_file
local token_file = opts.token_file
local token_url = opts.token_url or TOKEN_URL
if not credentials_file then
error("gcal: credentials_file is required")
end
if not token_file then
error("gcal: token_file is required")
end
local auth = oauth2.from_file(credentials_file, token_file, {
token_url = token_url,
})
local api_base = opts.api_base or GCAL_API
local function get_headers()
return auth:headers()
end
local function refresh_auth()
auth:refresh()
auth:save()
end
local function api_get(path_str)
local resp = http.get(api_base .. path_str, { headers = get_headers() })
if resp.status == 401 then
refresh_auth()
resp = http.get(api_base .. path_str, { headers = get_headers() })
end
if resp.status == 404 then return nil end
if resp.status ~= 200 then
error("gcal: GET " .. path_str .. " HTTP " .. resp.status .. ": " .. resp.body)
end
return json.parse(resp.body)
end
local function api_post(path_str, payload)
local resp = http.post(api_base .. path_str, payload, { headers = get_headers() })
if resp.status == 401 then
refresh_auth()
resp = http.post(api_base .. path_str, payload, { headers = get_headers() })
end
if resp.status ~= 200 and resp.status ~= 201 then
error("gcal: POST " .. path_str .. " HTTP " .. resp.status .. ": " .. resp.body)
end
return json.parse(resp.body)
end
local function api_put(path_str, payload)
local resp = http.put(api_base .. path_str, payload, { headers = get_headers() })
if resp.status == 401 then
refresh_auth()
resp = http.put(api_base .. path_str, payload, { headers = get_headers() })
end
if resp.status ~= 200 then
error("gcal: PUT " .. path_str .. " HTTP " .. resp.status .. ": " .. resp.body)
end
return json.parse(resp.body)
end
local function api_delete(path_str)
local resp = http.delete(api_base .. path_str, { headers = get_headers() })
if resp.status == 401 then
refresh_auth()
resp = http.delete(api_base .. path_str, { headers = get_headers() })
end
if resp.status ~= 200 and resp.status ~= 204 then
error("gcal: DELETE " .. path_str .. " HTTP " .. resp.status .. ": " .. resp.body)
end
return true
end
local c = {}
c.events = {}
function c.events:list(events_opts)
events_opts = events_opts or {}
local params = {}
if events_opts.timeMin then params[#params + 1] = "timeMin=" .. events_opts.timeMin end
if events_opts.timeMax then params[#params + 1] = "timeMax=" .. events_opts.timeMax end
if events_opts.maxResults then params[#params + 1] = "maxResults=" .. events_opts.maxResults end
if events_opts.q then params[#params + 1] = "q=" .. events_opts.q end
local qs = ""
if #params > 0 then qs = "?" .. table.concat(params, "&") end
local result = api_get("/calendar/v3/calendars/primary/events" .. qs)
if result and result.items then
return result.items
end
return {}
end
function c.events:get(event_id)
return api_get("/calendar/v3/calendars/primary/events/" .. event_id)
end
function c.events:create(event)
return api_post("/calendar/v3/calendars/primary/events", event)
end
function c.events:update(event_id, event)
return api_put("/calendar/v3/calendars/primary/events/" .. event_id, event)
end
function c.events:delete(event_id)
return api_delete("/calendar/v3/calendars/primary/events/" .. event_id)
end
c.calendars = {}
function c.calendars:list()
local result = api_get("/calendar/v3/users/me/calendarList")
if result and result.items then
return result.items
end
return {}
end
return c
end
return M