Google Calendar API Autherization
This commit is contained in:
parent
4f5a6e67af
commit
3adcff562f
1
.firsttimeruncheck
Normal file
1
.firsttimeruncheck
Normal file
@ -0,0 +1 @@
|
|||||||
|
true
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@
|
|||||||
# App Specific
|
# App Specific
|
||||||
sudoku*.png
|
sudoku*.png
|
||||||
data.json
|
data.json
|
||||||
|
client_secret.json
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
5
application/TODO
Normal file
5
application/TODO
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
TODO:
|
||||||
|
- check if first run (api call) and show google calendar login button
|
||||||
|
* schedule pypi every().day() or smth like that at (time to print)-5 minutes to update calendar and get ready to print new daily list
|
||||||
|
* parse calendar list to database format and call save_todos() with list of Todos
|
||||||
|
- Start uvicorn on device startup (using gunicorn + sysmtectl)
|
@ -10,14 +10,17 @@ from fastapi.staticfiles import StaticFiles
|
|||||||
from .utils import VerifyToken
|
from .utils import VerifyToken
|
||||||
from .database import TodoDatabase
|
from .database import TodoDatabase
|
||||||
from .thermal_print import ThermalPrinter
|
from .thermal_print import ThermalPrinter
|
||||||
|
from .sync_calendar import SyncData
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
|
import os
|
||||||
# from wsgiref import simple_server
|
# from wsgiref import simple_server
|
||||||
|
|
||||||
# Creates app instance
|
# Creates app instance
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
auth = VerifyToken()
|
auth = VerifyToken()
|
||||||
data = TodoDatabase()
|
data = TodoDatabase()
|
||||||
|
calendar = SyncData()
|
||||||
printer = ThermalPrinter(data)
|
printer = ThermalPrinter(data)
|
||||||
# printer.print_default() #temp debug
|
# printer.print_default() #temp debug
|
||||||
# printer.print_custom("Configuration Site: \n\n")
|
# printer.print_custom("Configuration Site: \n\n")
|
||||||
@ -69,21 +72,104 @@ class GoogleUpdate(BaseModel):
|
|||||||
# }
|
# }
|
||||||
# return result
|
# return result
|
||||||
|
|
||||||
|
# import google.oauth2.credentials
|
||||||
|
# import google_auth_oauthlib.flow
|
||||||
|
# import googleapiclient.discovery
|
||||||
|
|
||||||
|
# from google.auth.transport.requests import Request
|
||||||
|
# from google.oauth2.credentials import Credentials
|
||||||
|
# import os
|
||||||
|
# import json
|
||||||
|
|
||||||
|
# from google_auth_oauthlib.flow import InstalledAppFlow
|
||||||
|
# from googleapiclient.discovery import build
|
||||||
|
# from googleapiclient.errors import HttpError
|
||||||
|
|
||||||
|
# scopes =
|
||||||
|
# SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
||||||
|
|
||||||
@app.post("/api/google/update")
|
@app.post("/api/google/update")
|
||||||
def write_todos(code: GoogleUpdate, auth_result: str = Security(auth.verify)):
|
def google_update(googleCode: GoogleUpdate, auth_result: str = Security(auth.verify)):
|
||||||
print(code.code)
|
|
||||||
|
if calendar.get_new_creds(googleCode.code):
|
||||||
|
calendar.get_calendar_events()
|
||||||
|
with open(".firsttimeruncheck", 'w') as f:
|
||||||
|
f.write("true")
|
||||||
return {"status": "success"}
|
return {"status": "success"}
|
||||||
|
return {"status": "error"}
|
||||||
|
|
||||||
|
|
||||||
|
# print(googleCode.code)
|
||||||
|
|
||||||
|
# creds = None
|
||||||
|
|
||||||
|
# if os.path.exists('token.json'):
|
||||||
|
# creds = Credentials.from_authorized_user_file('token.json', SCOPES)
|
||||||
|
# # else:
|
||||||
|
# # flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
||||||
|
# # 'client_secret.json',
|
||||||
|
# # scopes=['https://www.googleapis.com/auth/calendar.readonly'],
|
||||||
|
# # redirect_uri="postmessage"
|
||||||
|
# # # state=state
|
||||||
|
# # )
|
||||||
|
|
||||||
|
# # creds = flow.fetch_token(code=googleCode.code)
|
||||||
|
# # print(creds)
|
||||||
|
# # with open("token.json", 'w') as token:
|
||||||
|
# # token.write(creds.to_json())
|
||||||
|
|
||||||
|
# if not creds or not creds.valid:
|
||||||
|
# if creds and creds.expired and creds.refresh_token:
|
||||||
|
# creds.refresh(Request())
|
||||||
|
# else:
|
||||||
|
# # flow = InstalledAppFlow.from_client_secrets_file(
|
||||||
|
# # 'credentials.json', SCOPES)
|
||||||
|
# # creds = flow.run_local_server(port=0)
|
||||||
|
|
||||||
|
# flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
||||||
|
# 'client_secret.json',
|
||||||
|
# scopes=SCOPES,
|
||||||
|
# redirect_uri="postmessage"
|
||||||
|
# # state=state
|
||||||
|
# )
|
||||||
|
# flow.fetch_token(code=googleCode.code)
|
||||||
|
# creds = flow.credentials
|
||||||
|
# # print(creds)
|
||||||
|
|
||||||
|
# # Save the credentials for the next run
|
||||||
|
# with open('token.json', 'w') as token:
|
||||||
|
# token.write(creds.to_json())
|
||||||
|
# # json.dump(token, creds)
|
||||||
|
|
||||||
|
|
||||||
|
# # if not creds or not creds.valid:
|
||||||
|
# # return {"status": "google already autherized"}
|
||||||
|
# # creds = Credentials.from_authorized_user_file('token.json', SCOPES)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.get('/api/first_run')
|
@app.get('/api/first_run')
|
||||||
def first_run():
|
def first_run():
|
||||||
try:
|
if os.path.exists('.firsttimeruncheck'):
|
||||||
with open('.firsttimeruncheck', 'x') as f:
|
with open('.firsttimeruncheck', 'r') as f:
|
||||||
f.write("")
|
data = f.read()
|
||||||
return {"status": "First Run"}
|
if data == "true":
|
||||||
except OSError as e:
|
|
||||||
print(e)
|
|
||||||
if e.errno == errno.EEXIST:
|
|
||||||
return {"status": "Not First Run"}
|
return {"status": "Not First Run"}
|
||||||
|
else:
|
||||||
|
with open('.firsttimeruncheck', 'w') as f:
|
||||||
|
f.write("false")
|
||||||
|
|
||||||
|
return {"status": "First Run"}
|
||||||
|
# try:
|
||||||
|
# with open('.firsttimeruncheck', 'x') as f:
|
||||||
|
# f.write("")
|
||||||
|
# return {"status": "First Run"}
|
||||||
|
# except OSError as e:
|
||||||
|
# print(e)
|
||||||
|
# if e.errno == errno.EEXIST:
|
||||||
|
# return {"status": "Not First Run"}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,8 +18,17 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button onclick="client.requestCode();">Authorize with Google</button>
|
|
||||||
|
|
||||||
|
<div id="googleAuthModel" class="absolute w-full h-full overflow-y-hidden top-0 left-0 hidden">
|
||||||
|
<div class="flex flex-row w-full justify-center items-center text-center h-screen">
|
||||||
|
<div class="absolute w-full h-full bg-slate-800 opacity-40 top-0 left-0"></div>
|
||||||
|
<div class="bg-white inline-block rounded-lg overflow-hidden align-bottom transition-all transform shadow-2xl sm:my-8 sm:align-middle sm:max-w-xl sm:w-full pt-6 pb-6">
|
||||||
|
<h3 class="font-semibold ">Link your google calendar: </h3><br>
|
||||||
|
<button class="bg-indigo-500 text-white p-4 rounded-md" onclick="client.requestCode();">Authorize with Google</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <div id="testToken"></div> -->
|
<!-- <div id="testToken"></div> -->
|
||||||
|
|
||||||
@ -453,28 +462,83 @@
|
|||||||
<script src="https://accounts.google.com/gsi/client"></script>
|
<script src="https://accounts.google.com/gsi/client"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
let code_receiver_uri = "/api/google/update"
|
// let first_run = null
|
||||||
|
// let test =
|
||||||
|
// console.log(test)
|
||||||
|
|
||||||
const client = google.accounts.oauth2.initCodeClient({
|
// let client = null
|
||||||
client_id: '186960779149-ejtu6hh3kdatlouau80h2pivt4tv3hd0.apps.googleusercontent.com',
|
|
||||||
scope: 'https://www.googleapis.com/auth/calendar.readonly',
|
|
||||||
ux_mode: 'popup',
|
|
||||||
callback: (response) => {
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('POST', code_receiver_uri, true);
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
||||||
xhr.setRequestHeader('Authorization', 'Bearer ' + jToken);
|
|
||||||
// Set custom header for CRSF
|
|
||||||
xhr.setRequestHeader('X-Requested-With', 'XmlHttpRequest');
|
|
||||||
xhr.onload = function() {
|
|
||||||
console.log('Auth code response: ' + xhr.responseText);
|
|
||||||
};
|
|
||||||
xhr.send(JSON.stringify({"code": response.code}));
|
|
||||||
console.log(xhr)
|
|
||||||
console.log(response.code)
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// async function mainAsync() {
|
||||||
|
// console.log('huh')
|
||||||
|
// async function check_first_run() {
|
||||||
|
// let res = await fetch("/api/first_run")
|
||||||
|
// let resJ = await res.json()
|
||||||
|
// return resJ
|
||||||
|
// // return fetch("/api/first_run").then(r => {
|
||||||
|
// // return r.json().then(j => {
|
||||||
|
// // first_run = j
|
||||||
|
// // console.log(j)
|
||||||
|
// // return j
|
||||||
|
// // })
|
||||||
|
// // })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let first_run_status = await check_first_run()
|
||||||
|
// if (first_run_status["status"] === "First Run") {
|
||||||
|
// document.getElementById("googleAuthModel").classList.remove("hidden")
|
||||||
|
// let code_receiver_uri = "/api/google/update"
|
||||||
|
|
||||||
|
// client = google.accounts.oauth2.initCodeClient({
|
||||||
|
// client_id: '186960779149-ejtu6hh3kdatlouau80h2pivt4tv3hd0.apps.googleusercontent.com',
|
||||||
|
// scope: 'https://www.googleapis.com/auth/calendar.readonly',
|
||||||
|
// ux_mode: 'popup',
|
||||||
|
// callback: (response) => {
|
||||||
|
// const xhr = new XMLHttpRequest();
|
||||||
|
// xhr.open('POST', code_receiver_uri, true);
|
||||||
|
// xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
// xhr.setRequestHeader('Authorization', 'Bearer ' + jToken);
|
||||||
|
// // Set custom header for CRSF
|
||||||
|
// xhr.setRequestHeader('X-Requested-With', 'XmlHttpRequest');
|
||||||
|
// xhr.onload = function() {
|
||||||
|
// console.log('Auth code response: ' + xhr.responseText);
|
||||||
|
// document.getElementById("googleAuthModel").classList.add("hidden")
|
||||||
|
// };
|
||||||
|
// xhr.send(JSON.stringify({"code": response.code}));
|
||||||
|
// console.log(xhr)
|
||||||
|
// console.log(response.code)
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // console.log(test)
|
||||||
|
|
||||||
|
// // console.log(first_run)
|
||||||
|
|
||||||
|
|
||||||
|
// // function check_first_run() {
|
||||||
|
// // let first_run = ""
|
||||||
|
// // const req = new XMLHttpRequest();
|
||||||
|
// // // req.addEventListener("load", reqListener);
|
||||||
|
// // req.open("GET", "/api/first_run", false);
|
||||||
|
// // req.onload = function() {
|
||||||
|
// // first_run = req.responseText
|
||||||
|
// // // console.log(first_run)
|
||||||
|
// // }
|
||||||
|
// // req.send();
|
||||||
|
// // return first_run
|
||||||
|
// // console.log(first_run)
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // console.log(check_first_run())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mainAsync()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="scripts.js"></script>
|
<script src="scripts.js"></script>
|
||||||
|
@ -638,6 +638,7 @@ function loginAction(e) {
|
|||||||
// console.log(t)
|
// console.log(t)
|
||||||
jToken = t
|
jToken = t
|
||||||
getTodosFromAPI()
|
getTodosFromAPI()
|
||||||
|
mainAsync()
|
||||||
|
|
||||||
// document.getElementById("testToken").innerHTML = t
|
// document.getElementById("testToken").innerHTML = t
|
||||||
|
|
||||||
@ -670,6 +671,79 @@ function loginAction(e) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let client = null
|
||||||
|
|
||||||
|
async function mainAsync() {
|
||||||
|
console.log('run async')
|
||||||
|
async function check_first_run() {
|
||||||
|
let res = await fetch("/api/first_run")
|
||||||
|
let resJ = await res.json()
|
||||||
|
return resJ
|
||||||
|
// return fetch("/api/first_run").then(r => {
|
||||||
|
// return r.json().then(j => {
|
||||||
|
// first_run = j
|
||||||
|
// console.log(j)
|
||||||
|
// return j
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_run_status = await check_first_run()
|
||||||
|
if (first_run_status["status"] === "First Run") {
|
||||||
|
document.getElementById("googleAuthModel").classList.remove("hidden")
|
||||||
|
let code_receiver_uri = "/api/google/update"
|
||||||
|
|
||||||
|
client = google.accounts.oauth2.initCodeClient({
|
||||||
|
client_id: '186960779149-ejtu6hh3kdatlouau80h2pivt4tv3hd0.apps.googleusercontent.com',
|
||||||
|
scope: 'https://www.googleapis.com/auth/calendar.readonly',
|
||||||
|
ux_mode: 'popup',
|
||||||
|
callback: (response) => {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('POST', code_receiver_uri, true);
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
xhr.setRequestHeader('Authorization', 'Bearer ' + jToken);
|
||||||
|
// Set custom header for CRSF
|
||||||
|
xhr.setRequestHeader('X-Requested-With', 'XmlHttpRequest');
|
||||||
|
xhr.onload = function() {
|
||||||
|
console.log('Auth code response: ' + xhr.responseText);
|
||||||
|
document.getElementById("googleAuthModel").classList.add("hidden")
|
||||||
|
};
|
||||||
|
xhr.send(JSON.stringify({"code": response.code}));
|
||||||
|
console.log(xhr)
|
||||||
|
console.log(response.code)
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(test)
|
||||||
|
|
||||||
|
// console.log(first_run)
|
||||||
|
|
||||||
|
|
||||||
|
// function check_first_run() {
|
||||||
|
// let first_run = ""
|
||||||
|
// const req = new XMLHttpRequest();
|
||||||
|
// // req.addEventListener("load", reqListener);
|
||||||
|
// req.open("GET", "/api/first_run", false);
|
||||||
|
// req.onload = function() {
|
||||||
|
// first_run = req.responseText
|
||||||
|
// // console.log(first_run)
|
||||||
|
// }
|
||||||
|
// req.send();
|
||||||
|
// return first_run
|
||||||
|
// console.log(first_run)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// console.log(check_first_run())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function getTodosFromAPI(day=dayjs().format("YYYY-MM-DD")) {
|
function getTodosFromAPI(day=dayjs().format("YYYY-MM-DD")) {
|
||||||
document.getElementById("loginPanel").classList.add("hidden")
|
document.getElementById("loginPanel").classList.add("hidden")
|
||||||
|
@ -1,7 +1,164 @@
|
|||||||
#TODO: All Google/iCloud Calendar syncing logic here
|
#TODO: All Google/iCloud Calendar syncing logic here
|
||||||
|
|
||||||
|
import google_auth_oauthlib.flow
|
||||||
|
from google.auth.transport.requests import Request
|
||||||
|
from google.oauth2.credentials import Credentials
|
||||||
|
from googleapiclient.discovery import build
|
||||||
|
from googleapiclient.errors import HttpError
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
from .database import TodoDatabase
|
||||||
|
|
||||||
|
data = TodoDatabase()
|
||||||
|
|
||||||
|
|
||||||
|
from datetime import datetime, time, timedelta
|
||||||
|
import pytz
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
from datetime import timezone
|
||||||
|
|
||||||
|
def midnight_UTC(offset):
|
||||||
|
|
||||||
|
# Construct a timezone object
|
||||||
|
tz = pytz.timezone('America/Toronto')
|
||||||
|
|
||||||
|
# Work out today/now as a timezone-aware datetime
|
||||||
|
today = datetime.now(tz)
|
||||||
|
|
||||||
|
# Adjust by the offset. Note that that adding 1 day might actually move us 23 or 25
|
||||||
|
# hours into the future, depending on daylight savings. This works because the {today}
|
||||||
|
# variable is timezone aware
|
||||||
|
target_day = today + timedelta(days=1) * offset
|
||||||
|
|
||||||
|
# Discard hours, minutes, seconds and microseconds
|
||||||
|
midnight_aware = tz.localize(
|
||||||
|
datetime.combine(target_day, time(0, 0, 0, 0)), is_dst=None)
|
||||||
|
|
||||||
|
# Convert to UTC
|
||||||
|
midnight_UTC = midnight_aware.astimezone(pytz.utc)
|
||||||
|
|
||||||
|
return midnight_UTC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SyncData():
|
class SyncData():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
|
||||||
|
self.creds = None
|
||||||
|
|
||||||
|
self.get_new_creds()
|
||||||
|
self.get_calendar_events()
|
||||||
|
|
||||||
|
|
||||||
|
def get_new_creds(self, code=""):
|
||||||
|
"""Returns True if successfully obtains credentials,
|
||||||
|
otherwise throws errors according to functions called, unless
|
||||||
|
code='' in which case if no saved credentials are found, returns False
|
||||||
|
"""
|
||||||
|
if os.path.exists('token.json'):
|
||||||
|
self.creds = Credentials.from_authorized_user_file('token.json', self.SCOPES)
|
||||||
|
# else:
|
||||||
|
# flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
||||||
|
# 'client_secret.json',
|
||||||
|
# scopes=['https://www.googleapis.com/auth/calendar.readonly'],
|
||||||
|
# redirect_uri="postmessage"
|
||||||
|
# # state=state
|
||||||
|
# )
|
||||||
|
|
||||||
|
# creds = flow.fetch_token(code=googleCode.code)
|
||||||
|
# print(creds)
|
||||||
|
# with open("token.json", 'w') as token:
|
||||||
|
# token.write(creds.to_json())
|
||||||
|
|
||||||
|
if not self.creds or not self.creds.valid:
|
||||||
|
if self.creds and self.creds.expired and self.creds.refresh_token:
|
||||||
|
self.creds.refresh(Request())
|
||||||
|
else:
|
||||||
|
if code == "":
|
||||||
|
return False
|
||||||
|
# flow = InstalledAppFlow.from_client_secrets_file(
|
||||||
|
# 'credentials.json', SCOPES)
|
||||||
|
# creds = flow.run_local_server(port=0)
|
||||||
|
|
||||||
|
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
|
||||||
|
'client_secret.json',
|
||||||
|
scopes=self.SCOPES,
|
||||||
|
redirect_uri="postmessage"
|
||||||
|
# state=state
|
||||||
|
)
|
||||||
|
flow.fetch_token(code=code)
|
||||||
|
self.creds = flow.credentials
|
||||||
|
# print(creds)
|
||||||
|
|
||||||
|
# Save the credentials for the next run
|
||||||
|
with open('token.json', 'w') as token:
|
||||||
|
token.write(self.creds.to_json())
|
||||||
|
# json.dump(token, creds)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_calendar_events(self, day=None):
|
||||||
|
self.get_new_creds()
|
||||||
|
|
||||||
|
# now = datetime.now()
|
||||||
|
# if day:
|
||||||
|
# now = datetime.datetime.strptime(day, "%Y-%m-%d")
|
||||||
|
# else:
|
||||||
|
# now = datetime.datetime.now()
|
||||||
|
# day_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
|
# day_end = day_start + datetime.timedelta(hours=24)
|
||||||
|
# day_start = day_start.isoformat() + "Z"
|
||||||
|
# day_end = day_end.isoformat() + "Z"
|
||||||
|
|
||||||
|
if day:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
# day_start = midnight_UTC(0).isoformat() + "Z"
|
||||||
|
# day_end = midnight_UTC(1).isoformat() + "Z"
|
||||||
|
day_start = datetime.combine(datetime.now(tz=ZoneInfo("America/Toronto")).date(), time(0, 0), tzinfo=ZoneInfo("America/Toronto"))
|
||||||
|
day_end = day_start + timedelta(hours=23,minutes=59)
|
||||||
|
# day_start_for = day_start.astimezone(ZoneInfo("UTC")).isoformat() + "Z"
|
||||||
|
# day_end_for = day_end.astimezone(ZoneInfo("UTC")).isoformat() + "Z"
|
||||||
|
day_start_for = day_start.astimezone(ZoneInfo("UTC")).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
|
||||||
|
day_end_for = day_end.astimezone(ZoneInfo("UTC")).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
|
||||||
|
|
||||||
|
# print(day_start.tzname())
|
||||||
|
print(day_start)
|
||||||
|
print(day_end)
|
||||||
|
print(day_start.astimezone(ZoneInfo("UTC")).strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
|
||||||
|
print(day_end.astimezone(ZoneInfo("UTC")).strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
|
||||||
|
print(datetime.utcnow().isoformat() + 'Z')
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
service = build('calendar', 'v3', credentials=self.creds)
|
||||||
|
|
||||||
|
# Call the Calendar API
|
||||||
|
# now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
|
||||||
|
print('Getting all upcoming events for time range: ' + day_start_for + " to " + day_end_for)
|
||||||
|
events_result = service.events().list(calendarId='primary', timeMin=day_start_for, timeMax=day_end_for,
|
||||||
|
singleEvents=True, orderBy='startTime').execute()
|
||||||
|
events = events_result.get('items', [])
|
||||||
|
|
||||||
|
if not events:
|
||||||
|
print('No upcoming events found.')
|
||||||
|
return
|
||||||
|
|
||||||
|
# Prints the start and name of the next 10 events
|
||||||
|
# event format: {'kind': 'calendar#event', 'etag': '"3386046190326000"', 'id': '0migcv6t729ph1kirhiauej3eh', 'status': 'confirmed', 'htmlLink': 'https://www.google.com/calendar/event?eid=MG1pZ2N2NnQ3MjlwaDFraXJoaWF1ZWozZWggYmFtLmltLnNhbUBt', 'created': '2023-08-26T04:11:35.000Z', 'updated': '2023-08-26T04:11:35.163Z', 'summary': 'test', 'creator': {'email': 'bam.im.sam@gmail.com', 'self': True}, 'organizer': {'email': 'bam.im.sam@gmail.com', 'self': True}, 'start': {'dateTime': '2023-08-27T14:30:00-04:00', 'timeZone': 'America/Toronto'}, 'end': {'dateTime': '2023-08-27T15:30:00-04:00', 'timeZone': 'America/Toronto'}, 'iCalUID': '0migcv6t729ph1kirhiauej3eh@google.com', 'sequence': 0, 'reminders': {'useDefault': True}, 'eventType': 'default'}
|
||||||
|
for event in events:
|
||||||
|
print(event)
|
||||||
|
start = event['start'].get('dateTime', event['start'].get('date'))
|
||||||
|
end = event['end'].get('dateTime', event['end'].get('date'))
|
||||||
|
print(start, "->", end, event['summary'])
|
||||||
|
|
||||||
|
except HttpError as error:
|
||||||
|
print('An error occurred: %s' % error)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#TODO: Obtain calendar data and save to local database, parse into printable content
|
#TODO: Obtain calendar data and save to local database, parse into printable content
|
||||||
|
1
client_secret.json.example
Normal file
1
client_secret.json.example
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"web":{"client_id":"","project_id":"thermaltodos","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"","javascript_origins":["https://thermaltodos.imsam.ca"]}}
|
Loading…
Reference in New Issue
Block a user