Update calendar registration to use TV and Limited Input Device flow

This commit is contained in:
ChuckBuilds
2025-04-21 09:24:42 -05:00
parent f4b37d012b
commit c02f80ead7

View File

@@ -5,8 +5,7 @@ from google_auth_oauthlib.flow import InstalledAppFlow
from google.oauth2.credentials import Credentials from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request from google.auth.transport.requests import Request
import pickle import pickle
import urllib.parse import requests
import socket
# If modifying these scopes, delete the file token.pickle. # If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'] SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
@@ -20,6 +19,28 @@ def save_credentials(creds, token_path):
with open(token_path, 'wb') as token: with open(token_path, 'wb') as token:
pickle.dump(creds, token) pickle.dump(creds, token)
def get_device_code(client_id, client_secret):
"""Get device code for TV and Limited Input Device flow."""
url = 'https://oauth2.googleapis.com/device/code'
data = {
'client_id': client_id,
'scope': ' '.join(SCOPES)
}
response = requests.post(url, data=data)
return response.json()
def poll_for_token(client_id, client_secret, device_code):
"""Poll for token using device code."""
url = 'https://oauth2.googleapis.com/token'
data = {
'client_id': client_id,
'client_secret': client_secret,
'device_code': device_code,
'grant_type': 'urn:ietf:params:oauth:grant-type:device_code'
}
response = requests.post(url, data=data)
return response.json()
def main(): def main():
config = load_config() config = load_config()
calendar_config = config.get('calendar', {}) calendar_config = config.get('calendar', {})
@@ -43,34 +64,54 @@ def main():
print("1. Go to https://console.cloud.google.com") print("1. Go to https://console.cloud.google.com")
print("2. Create a project or select existing project") print("2. Create a project or select existing project")
print("3. Enable the Google Calendar API") print("3. Enable the Google Calendar API")
print("4. Configure the OAuth consent screen") print("4. Configure the OAuth consent screen (select TV and Limited Input Device)")
print("5. Create OAuth 2.0 credentials (Desktop application)") print("5. Create OAuth 2.0 credentials (TV and Limited Input Device)")
print("6. Download the credentials and save as credentials.json") print("6. Download the credentials and save as credentials.json")
return return
# Create the flow using the client secrets file from the Google API Console # Load client credentials
flow = InstalledAppFlow.from_client_secrets_file( with open(creds_file, 'r') as f:
creds_file, SCOPES, client_config = json.load(f)
redirect_uri='urn:ietf:wg:oauth:2.0:oob' # Use out-of-band flow for headless environment
)
# Generate URL for authorization client_id = client_config['installed']['client_id']
auth_url, _ = flow.authorization_url(prompt='consent') client_secret = client_config['installed']['client_secret']
print("\nPlease visit this URL to authorize this application:") # Get device code
print(auth_url) device_info = get_device_code(client_id, client_secret)
print("\nAfter authorizing, you will receive a code. Enter that code below:")
code = input("Enter the authorization code: ") print("\nTo authorize this application, visit:")
print(device_info['verification_url'])
print("\nAnd enter the code:")
print(device_info['user_code'])
print("\nWaiting for authorization...")
# Exchange the authorization code for credentials # Poll for token
flow.fetch_token(code=code) while True:
creds = flow.credentials token_info = poll_for_token(client_id, client_secret, device_info['device_code'])
# Save the credentials if 'access_token' in token_info:
save_credentials(creds, token_file) # Create credentials object
print(f"\nCredentials saved successfully to {token_file}") creds = Credentials(
print("You can now run the LED Matrix display with calendar integration!") token=token_info['access_token'],
refresh_token=token_info.get('refresh_token'),
token_uri="https://oauth2.googleapis.com/token",
client_id=client_id,
client_secret=client_secret,
scopes=SCOPES
)
# Save the credentials
save_credentials(creds, token_file)
print(f"\nCredentials saved successfully to {token_file}")
print("You can now run the LED Matrix display with calendar integration!")
break
elif token_info.get('error') == 'authorization_pending':
import time
time.sleep(device_info['interval'])
else:
print(f"\nError during authorization: {token_info.get('error')}")
print("Please try again.")
return
if __name__ == '__main__': if __name__ == '__main__':
main() main()