Google Calendar API Oauth and Events List

Post your working scripts, libraries and tools for AHK v1.1 and older
Tre4shunter
Posts: 139
Joined: 26 Jan 2016, 16:05

Google Calendar API Oauth and Events List

04 Dec 2016, 18:46

Hi All,

Recently had a project where i needed to do full duplex synchronization between our companys internal calendar DB, and Google calendar - so ive spent some time with the calendar API - figure someone may find the functions useful.

You must enable API access for this to work, and fill the following in on the script:

Code: Select all

Global clientid = "************************"
Global calname = "**********************"
Global ClientSecret = "*************"
There are many resources online about how to get that information, but if you cant figure it out just let me know and ill help you out.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

Global GGL_Refresh_Url = "https://accounts.google.com/o/oauth2/token"
Global authURL = "https://accounts.google.com/o/oauth2/auth?"
Global Stringredirect = "urn:ietf:wg:oauth:2.0:oob"
Global scope = "https://www.googleapis.com/auth/calendar"


Global clientid =
Global calname = 
Global ClientSecret = 


Global GGL_Refresh_Headers = {"Content-Type":"application/x-www-form-urlencoded"}
Global GGL_Token_Request_URLParams = {"redirect_uri":Stringredirect,"response_type":"code","client_id":Clientid,"scope":scope}
Global Token_Request = {1:{"code":""},2:{"client_id":clientid},3:{"client_secret":clientsecret},4:{"redirect_uri":stringredirect},5:{"grant_type":"authorization_code"}}
Global GGL_Request_Headers = {"Gdata-Version":"3.0","Content-Type":"application/json","Authorization":GGL_API_Key}

gui,Add,Edit,w400 vToken,[Paste Text from Window Here]
gui,Add,Button,gButton,Submit

for k,v in GGL_Token_Request_URLParams
	Params .= k "=" v "&"
authurl .= Params

ie := ComObjCreate("InternetExplorer.Application")
ie.Navigate(authurl)
ie.visible := true
Gui,show,autosize
return

Button:
gui,submit
if(!Token)
	return

Token_Request[1,"code"] := Token
Results := ListGoogleEvents("New")
a(Results)
return

exitapp



;Make HTTP POST/GET/PATCH/DELETE Requests with Params and headers
sendstring(type, url, body="", Headers="", URLParams="")
{
	pwhr := comobjcreate("MSXML2.ServerXMLHTTP")	
	for k,v in URLParams
		Params .= k "=" v "&"
	url := (isobject(URLParams)) ? url "?" substr(params,1,-1)  : url
	pwhr.open(type, url, false)

	for k,v in Headers
		pwhr.setrequestheader(k,v)
	
	if isobject(body)
	{
		for k,v in body
		{
			for k1,v1 in v
				body .= k1 "=" v1 "&"
		}
		body:=substr(body,1,-1)
	}
	pwhr.Send(body)
	Response := pwhr.Responsetext
	return Response
}

;List all Updated and Cancelled Events from Google Calendar
ListGoogleEvents(RetType) 
{
	tkn := JSON1.Decode(Sendstring("POST",GGL_refresh_url,Token_Request,GGL_Refresh_Headers,"")).access_token
	GGL_Request_Headers["Authorization"] := "Bearer " tkn
	url = https://www.googleapis.com/calendar/v3/calendars/%calname%/events?syncToken=%syncTok%&key={YOUR_API_KEY}
	x := JSON1.Decode(sendstring("GET", Url,"",GGL_Request_Headers))
	
	Events:=[]
	EventsCancelled:=[]
	
	if(x.nextSyncToken <> ""){
		Events := Append(Events,x.items,"confirmed")
		EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
	}
	
	while (x.nextSyncToken = "")
	{
		pageToken := x.nextPageToken
		url = https://www.googleapis.com/calendar/v3/calendars/%calname%/events?pageToken=%pageToken%&syncToken=%syncTok%&key={YOUR_API_KEY}
		x:=JSON1.Decode(sendstring(`"GET`", url,"",GGL_Request_Headers))
		if(x.syncToken <> ""){
			Events := Append(Events,x.items,"confirmed")
			EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
		}else{
			Events := Append(Events,x.items,"confirmed")
			EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
		}
	}
	
	RetObj := (RetType="New") ? Events : EventsCancelled
	return RetObj
}

;Helper Function to Create Single List of Calendar Events From Google Queries
Append(Arr1,Arr2,Status) 
{
	for each, item in Arr2
		if (item.status = Status)
			Arr1.Push(item)
	else if(Status = "*")
		Arr1.Push(item)
	Return Arr1
}

A(Array, Parent="") 
{
	static
	global GuiArrayTree, GuiArrayTreeX, GuiArrayTreeY
	if Array_IsCircle(Array)
	{
		MsgBox, 16, GuiArray, Error: Circular refrence
		return "Error: Circular refrence"
	}
	if !Parent
	{
		Gui, +HwndDefault
		Gui, GuiArray:New, +HwndGuiArray +LabelGuiArray +Resize
		Gui, Add, TreeView, vGuiArrayTree
		
		Parent := "P1"
		%Parent% := TV_Add("Array", 0, "+Expand")
		A(Array, Parent)
		GuiControlGet, GuiArrayTree, Pos
		Gui, Show,, GuiArray
		Gui, %Default%:Default
		
		WinWaitActive, ahk_id%GuiArray%
		WinWaitClose, ahk_id%GuiArray%
		return
	}
	For Key, Value in Array
	{
		%Parent%C%A_Index% := TV_Add(Key, %Parent%)
		KeyParent := Parent "C" A_Index
		if (IsObject(Value))
			A(Value, KeyParent)
		else
			%KeyParent%C1 := TV_Add(Value, %KeyParent%)
	}
	return
	
	GuiArrayClose:
	Gui, Destroy
	return
	
	GuiArraySize:
	if !(A_GuiWidth || A_GuiHeight) ; Minimized
		return
	GuiControl, Move, GuiArrayTree, % "w" A_GuiWidth - (GuiArrayTreeX * 2) " h" A_GuiHeight - (GuiArrayTreeY * 2)
	return
}

Array_IsCircle(Obj, Objs=0) 
{
	if !Objs
		Objs := {}
	For Key, Val in Obj
		if (IsObject(Val)&&(Objs[&Val]||Array_IsCircle(Val,(Objs,Objs[&Val]:=1))))
			return 1
	return 0
}

class JSON1
{
	Decode(jsonStr){
		
		; Create the COM object we'll use to decode the string
		SC := ComObjCreate("ScriptControl") 
		SC.Language := "JScript"
		ComObjError(false)
		
		; This next part is a JScript (similar to JavaScript), not AHK, just FYI
		; This does the actual parsing
		jsCode =
		(
		function arrangeForAhkTraversing(obj){
			if(obj instanceof Array){
				for(var i=0 ; i<obj.length ; ++i)
					obj[i] = arrangeForAhkTraversing(obj[i]) ;
				return ['array',obj] ;
			}else if(obj instanceof Object){
				var keys = [], values = [] ;
				for(var key in obj){
					keys.push(key) ;
					values.push(arrangeForAhkTraversing(obj[key])) ;
				}
				return ['object',[keys,values]] ;
			}else
				return [typeof obj,obj] ;
		}
		)
		
		; Decode the JSON into an array (call the JS function above) using the COM object, then return an AHK object
		SC.ExecuteStatement(jsCode "; obj=" jsonStr)
		return this.convertJScriptObjToAhks( SC.Eval("arrangeForAhkTraversing(obj)") )
	}
	
	convertJScriptObjToAhks(jsObj){
		if(jsObj[0]="object"){
			obj := {}, keys := jsObj[1][0], values := jsObj[1][1]
			loop % keys.length
				obj[keys[A_INDEX-1]] := this.convertJScriptObjToAhks( values[A_INDEX-1] )
			return obj
		}else if(jsObj[0]="array"){
			array := []
			loop % jsObj[1].length
				array.insert(this.convertJScriptObjToAhks( jsObj[1][A_INDEX-1] ))
			return array
		}else
			return jsObj[1]
	}
}
This script just returns all events on the users calendar currently and displays them in a Treeview courtesy of GeekDudes Array_Gui function, which ive renamed just a() haha.

ListGoogleEvents("New") - Returns current events on calendar with no filter
ListGoogleEvents("Deleted") or just "" returns deleted calendar events

If anyone finds this useful - i can provide function examples for updating/adding/deleting events as well.

Thanks!

Treas
Tre4shunter
Posts: 139
Joined: 26 Jan 2016, 16:05

Re: Google Calendar API Oauth and Events List

05 Dec 2016, 22:25

Thanks TLM!

Also...I made an AHK calendar as well - heres a sneak peek! lol

With Google cal events listed:
http://imgur.com/a/9FQ7p

I'll post the cal interface if anyone is interested.
ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

Re: Google Calendar API Oauth and Events List

06 Dec 2016, 02:47

@Tre4shunter
I am interested if you want ot post the code for the AHK calendar.

Thanks in advance.
Tre4shunter
Posts: 139
Joined: 26 Jan 2016, 16:05

Re: Google Calendar API Oauth and Events List

06 Dec 2016, 08:08

Here you go ozzii:

Note - Ive commented out the lines to retrieve events from Gcal - simple add your own token information from the API and uncomment, it will load event summarys into the cal.

Have fun!

Code: Select all

SetBatchLines, -1


Global CurMonth
Global CurYear

Global GGL_Refresh_Url = "https://accounts.google.com/o/oauth2/token"
Global authURL = "https://accounts.google.com/o/oauth2/auth?"
Global Stringredirect = "urn:ietf:wg:oauth:2.0:oob"
Global scope = "https://www.googleapis.com/auth/calendar"

Global clientid = ""			;Get this information from the Google Developers Console
Global calname = ""
Global ClientSecret = ""
Global Refreshtoken = ""

Global GGL_Refresh_Headers = {"Content-Type":"application/x-www-form-urlencoded"}
Global GGL_Token_Request_URLParams = {"redirect_uri":Stringredirect,"response_type":"code","client_id":Clientid,"scope":scope}
Global GGL_Refresh_Body = {1:{"client_id":clientid},2:{"client_secret":clientsecret},3:{"refresh_token":refreshtoken},4:{"grant_type":"refresh_token"}}
Global Token_Request = {1:{"code":""},2:{"client_id":clientid},3:{"client_secret":clientsecret},4:{"redirect_uri":stringredirect},5:{"grant_type":"authorization_code"}}
Global GGL_Request_Headers = {"Gdata-Version":"3.0","Content-Type":"application/json","Authorization":GGL_API_Key}

DaySplit := Strsplit("Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",",")

Gui,1:Add,DateTime, w100 vDate gMonthCal,
Gui,1:Margin,1
gui,1:add, text, x1 w140  center Border section,% DaySplit[1]
Loop, 6
	gui,1:add, text, w140 ys center Border,% DaySplit[a_Index + 1]
gui,1:Show,,AHKCal

Start := DayOfWeek(A_YYYY A_MM 01 000000)
NumofDays := DaysInMonthYear(A_MM,A_YYYY)
CurMonth := A_MM
CurYear := A_YYYY
buildview(start,numofdays)
;GoogleEvents := ListGoogleEvents("New")		;Uncomment if you have proper google credentials
;Add(GoogleEvents)						;Uncomment if you have proper google credentials
return

Monthcal:
Gui,Submit,NoHide
FullDate := Substr(Date,1,6) "01000000"
Month := Substr(Date,5,2)
Year := Substr(Date,1,4)
CurMonth := Month
CurYear := Year
Start := DayOfWeek(FullDate)
NumofDays := DaysInMonthYear(Month,Year)
gui,2:Destroy
buildview(start,numofdays)
winset, Redraw
;Add(GoogleEvents)						;Uncomment if you have proper google credentials
return

ESC::
Guiclose:
Gui,2:Destroy
ExitApp

Add(EventData)
{
	Gui,2:Default
	for each,event in EventData
	{
		sDateTime := Event.Start.DateTime
		EventMonth := SubStr(sDateTime,6,2)
		EventYear := SubStr(sDateTime,1,4)
		EventDay := SubStr(sDateTime,9,2)
		If(EventMonth <> CurMonth) OR (EventYear <> CurYear)
			Continue
		Gui,ListView,Syslistview32%EventDay%
		LV_Add("",Event.Summary)
	}
	Gui,1:Default
}

DayOfWeek(DateString)
{
	formattime,DayInWeek,%DateString%,Wday
	return, DayInWeek
}

DaysInMonthYear(Month,Year)
{
	return [31,28 + (!Mod(Year,4) && !(Mod(Year,100)||Mod(Year,400)) || Mod(Year,100) ),31,30,31,30,31,31,30,31,30,31][ Month ]
}

BuildView(Start,NumOfDays)
{
	Global
	w=140
	h=140
	x=0
	y=1
	DayCount = 1
	Gui, 2: +Parent1
	Gui, 2: Margin,1
	Gui, 2: +0x40000000 -0x80C00000
	Loop, 42
	{	
		if(A_Index < Start){
			x+=141
			Continue
		}else if(DayCount>NumOfDays){
			Break
		}
		Remaind := mod(A_Index,7)
		gui, 2:add, Listview, w%w% h%h% x%x% y%y% grid NoSort ReadOnly 0x2000 vLV%DayCount%, % Daycount++
		
		If(Remaind <> 0)
		{
			x+=141
		}else{
			x=0
			y+=141
		}
	}
	daycount--
	Controlgetpos,,ypos,,Cheight,SysListView32%daycount%
	t:=ypos + Cheight
	Try
	{
		Gui,1:Show, h%t%,
		gui,2:show,x1 y50	
	}Catch{
		Gui,1:Show,H800
		gui,2:show,x1 y50	
		
	}
	
	return
}

;Make HTTP POST/GET/PATCH/DELETE Requests with Params and headers
sendstring(type, url, body="", Headers="", URLParams="")
{
	pwhr := comobjcreate("MSXML2.ServerXMLHTTP")	
	for k,v in URLParams
		Params .= k "=" v "&"
	url := (isobject(URLParams)) ? url "?" substr(params,1,-1)  : url
	pwhr.open(type, url, false)

	for k,v in Headers
		pwhr.setrequestheader(k,v)
	
	if isobject(body)
	{
		for k,v in body
		{
			for k1,v1 in v
				body .= k1 "=" v1 "&"
		}
		body:=substr(body,1,-1)
	}
	pwhr.Send(body)
	Response := pwhr.Responsetext
	return Response
}

;List all Updated and Cancelled Events from Google Calendar
ListGoogleEvents(RetType) 
{
	tkn := JSON1.Decode(Sendstring("POST",GGL_refresh_url,GGL_Refresh_Body,GGL_Refresh_Headers,"")).access_token
	GGL_Request_Headers["Authorization"] := "Bearer " tkn
	
	url = https://www.googleapis.com/calendar/v3/calendars/%calname%/events?syncToken=%syncTok%&key={YOUR_API_KEY}
	x := JSON1.Decode(sendstring("GET", Url,"",GGL_Request_Headers))
	
	Events:=[]
	EventsCancelled:=[]
	
	if(x.nextSyncToken <> ""){
		Events := Append(Events,x.items,"confirmed")
		EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
	}
	
	while (x.nextSyncToken = "")
	{
		pageToken := x.nextPageToken
		url = https://www.googleapis.com/calendar/v3/calendars/%calname%/events?pageToken=%pageToken%&syncToken=%syncTok%&key={YOUR_API_KEY}
		x:=JSON1.Decode(sendstring(`"GET`", url,"",GGL_Request_Headers))
		if(x.syncToken <> ""){
			Events := Append(Events,x.items,"confirmed")
			EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
		}else{
			Events := Append(Events,x.items,"confirmed")
			EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
		}
	}
	
	RetObj := (RetType="New") ? Events : EventsCancelled
	return RetObj
}

;Helper Function to Create Single List of Calendar Events From Google Queries
Append(Arr1,Arr2,Status) 
{
	for each, item in Arr2
		if (item.status = Status)
			Arr1.Push(item)
	else if(Status = "*")
		Arr1.Push(item)
	Return Arr1
}

A(Array, Parent="") 
{
	static
	global GuiArrayTree, GuiArrayTreeX, GuiArrayTreeY
	if Array_IsCircle(Array)
	{
		MsgBox, 16, GuiArray, Error: Circular refrence
		return "Error: Circular refrence"
	}
	if !Parent
	{
		Gui, +HwndDefault
		Gui, GuiArray:New, +HwndGuiArray +LabelGuiArray +Resize
		Gui, Add, TreeView, vGuiArrayTree
		
		Parent := "P1"
		%Parent% := TV_Add("Array", 0, "+Expand")
		A(Array, Parent)
		GuiControlGet, GuiArrayTree, Pos
		Gui, Show,, GuiArray
		Gui, %Default%:Default
		
		WinWaitActive, ahk_id%GuiArray%
		WinWaitClose, ahk_id%GuiArray%
		return
	}
	For Key, Value in Array
	{
		%Parent%C%A_Index% := TV_Add(Key, %Parent%)
		KeyParent := Parent "C" A_Index
		if (IsObject(Value))
			A(Value, KeyParent)
		else
			%KeyParent%C1 := TV_Add(Value, %KeyParent%)
	}
	return
	
	GuiArrayClose:
	Gui, Destroy
	return
	
	GuiArraySize:
	if !(A_GuiWidth || A_GuiHeight) ; Minimized
		return
	GuiControl, Move, GuiArrayTree, % "w" A_GuiWidth - (GuiArrayTreeX * 2) " h" A_GuiHeight - (GuiArrayTreeY * 2)
	return
}

Array_IsCircle(Obj, Objs=0) 
{
	if !Objs
		Objs := {}
	For Key, Val in Obj
		if (IsObject(Val)&&(Objs[&Val]||Array_IsCircle(Val,(Objs,Objs[&Val]:=1))))
			return 1
	return 0
}

class JSON1
{
	Decode(jsonStr){
		
		; Create the COM object we'll use to decode the string
		SC := ComObjCreate("ScriptControl") 
		SC.Language := "JScript"
		ComObjError(false)
		
		; This next part is a JScript (similar to JavaScript), not AHK, just FYI
		; This does the actual parsing
		jsCode =
		(
		function arrangeForAhkTraversing(obj){
			if(obj instanceof Array){
				for(var i=0 ; i<obj.length ; ++i)
					obj[i] = arrangeForAhkTraversing(obj[i]) ;
				return ['array',obj] ;
			}else if(obj instanceof Object){
				var keys = [], values = [] ;
				for(var key in obj){
					keys.push(key) ;
					values.push(arrangeForAhkTraversing(obj[key])) ;
				}
				return ['object',[keys,values]] ;
			}else
				return [typeof obj,obj] ;
		}
		)
		
		; Decode the JSON into an array (call the JS function above) using the COM object, then return an AHK object
		SC.ExecuteStatement(jsCode "; obj=" jsonStr)
		return this.convertJScriptObjToAhks( SC.Eval("arrangeForAhkTraversing(obj)") )
	}
	
	convertJScriptObjToAhks(jsObj){
		if(jsObj[0]="object"){
			obj := {}, keys := jsObj[1][0], values := jsObj[1][1]
			loop % keys.length
				obj[keys[A_INDEX-1]] := this.convertJScriptObjToAhks( values[A_INDEX-1] )
			return obj
		}else if(jsObj[0]="array"){
			array := []
			loop % jsObj[1].length
				array.insert(this.convertJScriptObjToAhks( jsObj[1][A_INDEX-1] ))
			return array
		}else
			return jsObj[1]
	}
}
ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

Re: Google Calendar API Oauth and Events List

07 Dec 2016, 03:20

@Tre4shunter
Thanks. I will try this
slimpickens
Posts: 9
Joined: 04 Jul 2017, 06:41

Re: Google Calendar API Oauth and Events List

04 Jul 2017, 06:46

Hello, this looks great!
Now a quick question as I've not used the calendar api before, where do I find the calname?

Thanks!

Edit: I found it by logging on to calendar.google.com, here I found the calendar name on the left hand side. You can rename the calendar by clicking the arrow next to the name and choosing Calendar Settings.
humms
Posts: 2
Joined: 23 Nov 2019, 05:24
Contact:

Re: Google Calendar API Oauth and Events List

24 Nov 2019, 04:01

Good job man :thumbup:
I am interested if you want ot post the code for the AHK calendar.
carno
Posts: 265
Joined: 20 Jun 2014, 16:48

Re: Google Calendar API Oauth and Events List

28 Nov 2019, 22:49

Does this code still work with Google Calendar circa 2019-2020? And where/how do I get the following information? :geek:

Global clientid = ""
Global calname = ""
Global ClientSecret = ""
Global Refreshtoken = "

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

Global GGL_Refresh_Url = "https://accounts.google.com/o/oauth2/token"
Global authURL = "https://accounts.google.com/o/oauth2/auth?"
Global Stringredirect = "urn:ietf:wg:oauth:2.0:oob"
Global scope = "https://www.googleapis.com/auth/calendar"


Global clientid =
Global calname = 
Global ClientSecret = 


Global GGL_Refresh_Headers = {"Content-Type":"application/x-www-form-urlencoded"}
Global GGL_Token_Request_URLParams = {"redirect_uri":Stringredirect,"response_type":"code","client_id":Clientid,"scope":scope}
Global Token_Request = {1:{"code":""},2:{"client_id":clientid},3:{"client_secret":clientsecret},4:{"redirect_uri":stringredirect},5:{"grant_type":"authorization_code"}}
Global GGL_Request_Headers = {"Gdata-Version":"3.0","Content-Type":"application/json","Authorization":GGL_API_Key}

gui,Add,Edit,w400 vToken,[Paste Text from Window Here]
gui,Add,Button,gButton,Submit

for k,v in GGL_Token_Request_URLParams
	Params .= k "=" v "&"
authurl .= Params

ie := ComObjCreate("InternetExplorer.Application")
ie.Navigate(authurl)
ie.visible := true
Gui,show,autosize
return

Button:
gui,submit
if(!Token)
	return

Token_Request[1,"code"] := Token
Results := ListGoogleEvents("New")
a(Results)
return

exitapp



;Make HTTP POST/GET/PATCH/DELETE Requests with Params and headers
sendstring(type, url, body="", Headers="", URLParams="")
{
	pwhr := comobjcreate("MSXML2.ServerXMLHTTP")	
	for k,v in URLParams
		Params .= k "=" v "&"
	url := (isobject(URLParams)) ? url "?" substr(params,1,-1)  : url
	pwhr.open(type, url, false)

	for k,v in Headers
		pwhr.setrequestheader(k,v)
	
	if isobject(body)
	{
		for k,v in body
		{
			for k1,v1 in v
				body .= k1 "=" v1 "&"
		}
		body:=substr(body,1,-1)
	}
	pwhr.Send(body)
	Response := pwhr.Responsetext
	return Response
}

;List all Updated and Cancelled Events from Google Calendar
ListGoogleEvents(RetType) 
{
	tkn := JSON1.Decode(Sendstring("POST",GGL_refresh_url,Token_Request,GGL_Refresh_Headers,"")).access_token
	GGL_Request_Headers["Authorization"] := "Bearer " tkn
	url = https://www.googleapis.com/calendar/v3/calendars/%calname%/events?syncToken=%syncTok%&key={YOUR_API_KEY}
	x := JSON1.Decode(sendstring("GET", Url,"",GGL_Request_Headers))
	
	Events:=[]
	EventsCancelled:=[]
	
	if(x.nextSyncToken <> ""){
		Events := Append(Events,x.items,"confirmed")
		EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
	}
	
	while (x.nextSyncToken = "")
	{
		pageToken := x.nextPageToken
		url = https://www.googleapis.com/calendar/v3/calendars/%calname%/events?pageToken=%pageToken%&syncToken=%syncTok%&key={YOUR_API_KEY}
		x:=JSON1.Decode(sendstring(`"GET`", url,"",GGL_Request_Headers))
		if(x.syncToken <> ""){
			Events := Append(Events,x.items,"confirmed")
			EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
		}else{
			Events := Append(Events,x.items,"confirmed")
			EventsCancelled := Append(EventsCancelled,x.items,"cancelled")
		}
	}
	
	RetObj := (RetType="New") ? Events : EventsCancelled
	return RetObj
}

;Helper Function to Create Single List of Calendar Events From Google Queries
Append(Arr1,Arr2,Status) 
{
	for each, item in Arr2
		if (item.status = Status)
			Arr1.Push(item)
	else if(Status = "*")
		Arr1.Push(item)
	Return Arr1
}

A(Array, Parent="") 
{
	static
	global GuiArrayTree, GuiArrayTreeX, GuiArrayTreeY
	if Array_IsCircle(Array)
	{
		MsgBox, 16, GuiArray, Error: Circular refrence
		return "Error: Circular refrence"
	}
	if !Parent
	{
		Gui, +HwndDefault
		Gui, GuiArray:New, +HwndGuiArray +LabelGuiArray +Resize
		Gui, Add, TreeView, vGuiArrayTree
		
		Parent := "P1"
		%Parent% := TV_Add("Array", 0, "+Expand")
		A(Array, Parent)
		GuiControlGet, GuiArrayTree, Pos
		Gui, Show,, GuiArray
		Gui, %Default%:Default
		
		WinWaitActive, ahk_id%GuiArray%
		WinWaitClose, ahk_id%GuiArray%
		return
	}
	For Key, Value in Array
	{
		%Parent%C%A_Index% := TV_Add(Key, %Parent%)
		KeyParent := Parent "C" A_Index
		if (IsObject(Value))
			A(Value, KeyParent)
		else
			%KeyParent%C1 := TV_Add(Value, %KeyParent%)
	}
	return
	
	GuiArrayClose:
	Gui, Destroy
	return
	
	GuiArraySize:
	if !(A_GuiWidth || A_GuiHeight) ; Minimized
		return
	GuiControl, Move, GuiArrayTree, % "w" A_GuiWidth - (GuiArrayTreeX * 2) " h" A_GuiHeight - (GuiArrayTreeY * 2)
	return
}

Array_IsCircle(Obj, Objs=0) 
{
	if !Objs
		Objs := {}
	For Key, Val in Obj
		if (IsObject(Val)&&(Objs[&Val]||Array_IsCircle(Val,(Objs,Objs[&Val]:=1))))
			return 1
	return 0
}

class JSON1
{
	Decode(jsonStr){
		
		; Create the COM object we'll use to decode the string
		SC := ComObjCreate("ScriptControl") 
		SC.Language := "JScript"
		ComObjError(false)
		
		; This next part is a JScript (similar to JavaScript), not AHK, just FYI
		; This does the actual parsing
		jsCode =
		(
		function arrangeForAhkTraversing(obj){
			if(obj instanceof Array){
				for(var i=0 ; i<obj.length ; ++i)
					obj[i] = arrangeForAhkTraversing(obj[i]) ;
				return ['array',obj] ;
			}else if(obj instanceof Object){
				var keys = [], values = [] ;
				for(var key in obj){
					keys.push(key) ;
					values.push(arrangeForAhkTraversing(obj[key])) ;
				}
				return ['object',[keys,values]] ;
			}else
				return [typeof obj,obj] ;
		}
		)
		
		; Decode the JSON into an array (call the JS function above) using the COM object, then return an AHK object
		SC.ExecuteStatement(jsCode "; obj=" jsonStr)
		return this.convertJScriptObjToAhks( SC.Eval("arrangeForAhkTraversing(obj)") )
	}
	
	convertJScriptObjToAhks(jsObj){
		if(jsObj[0]="object"){
			obj := {}, keys := jsObj[1][0], values := jsObj[1][1]
			loop % keys.length
				obj[keys[A_INDEX-1]] := this.convertJScriptObjToAhks( values[A_INDEX-1] )
			return obj
		}else if(jsObj[0]="array"){
			array := []
			loop % jsObj[1].length
				array.insert(this.convertJScriptObjToAhks( jsObj[1][A_INDEX-1] ))
			return array
		}else
			return jsObj[1]
	}
}
User avatar
TLM
Posts: 1608
Joined: 01 Oct 2013, 07:52
Contact:

Re: Google Calendar API Oauth and Events List

10 Dec 2019, 16:55

carno wrote:
28 Nov 2019, 22:49
...where/how do I get the following information?
You have to generate them in your google console under *your project* > credentials
You have to request a returned Refreshtoken
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Google Calendar API Oauth and Events List

10 Dec 2019, 20:14

@Tre4shunter, this is great stuff.
Regards,
burque505
Tre4shunter
Posts: 139
Joined: 26 Jan 2016, 16:05

Re: Google Calendar API Oauth and Events List

12 Dec 2019, 17:24

@TLM the brilliant is right of course - however for my code to work, we don't actually need the Refreshtoken...it just grabs you a new Access Token each time.

Thank you @burque505 much appreciated :D

I'm working on a sweet new Calendar interface (Google Clone).....though, im not sure why really, haha

https://imgur.com/a/0wgDKJT
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Google Calendar API Oauth and Events List

12 Dec 2019, 17:56

@Tre4shunter, looks nice indeed, I'm looking forward to seeing a release!
Regards,
burque505
User avatar
TLM
Posts: 1608
Joined: 01 Oct 2013, 07:52
Contact:

Re: Google Calendar API Oauth and Events List

12 Dec 2019, 23:54

new interface @Tre4shunter? ooo hype :shock:
I use a Refresh Token in my web apps so I don't have to request a new Access Token all the time ;)
and you wouldn't want to exceed Google's 864,000 daily token request limit :lol:
pmobin
Posts: 17
Joined: 14 Apr 2016, 12:50

Re: Google Calendar API Oauth and Events List

09 Dec 2021, 20:15

Hello all,
I think the oauth process has changed recently. The developer console sends you to google cloud admin and that is more complex. I got the clientid and clientsecret strings but couldn't figure how to get the stringredirect. Using the existing stringredirect I get an error which I think is due to that. It comes from google as Authorization Error, Error 400:redirect_uri_mismatch. The redirect URI in the request, urn:ietf:wg:oauth:2.0:oob, can only be used by a Client ID for native application. It is not allowed for the WEB client type.

1- Where do I find or set that string?
2- If you have the rest of the operations figured out add an event, delete event etc, please share

Many thanks,
Farzad
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Google Calendar API Oauth and Events List

10 Dec 2021, 15:24

Read how create Your project here
https://developers.google.com/workspace/guides/create-project
and add http://localhost to Authorized redirect URIs at OAuth of Your web application.
pmobin
Posts: 17
Joined: 14 Apr 2016, 12:50

Re: Google Calendar API Oauth and Events List

11 Dec 2021, 21:03

Hi, I am looking for help in bringing up the code above and then onto bigger things. Have an app I am working on to be released soon and this is part of its prototype. If you are interested in consulting for a rate, drop me a note at [email protected]. Thank you. Farzad

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: Basi and 186 guests