Hi all,
I’ve hit a brick wall trying to access the YouTube API from Anvil… I’ve read https://anvil.works/docs/integrations/google/google-rest-apis and followed https://anvil.works/docs/integrations/google/linking-google-and-anvil with complete success for OAuth login using example scopes for Google Drive and Gmail, but get this error with the youtube.readonly scope:
Is there something special about the YouTube API? Is it blocked in server to server calls somehow - I ask that because I can successfully access the youtube.readonly scope using an alternate API Project which I set up as an “Installed App” API using just OAuth (no need for Client ID or Client secret) and an unverified Consent Screen.
Sample of my Anvil code:
scopes = [#"https://www.googleapis.com/auth/gmail.readonly",]
"https://www.googleapis.com//auth/youtube.readonly"]
self.gmail = anvil.google.drive.login()
self.token = anvil.google.auth.get_user_access_token()
print(self.gmail)
folder = anvil.google.drive.get_user_files()
self.token = anvil.google.auth.get_user_access_token()
for f in folder.list_files():
print(f)
self.gmail = anvil.google.auth.login(scopes) # fails here
self.token = anvil.google.auth.get_user_access_token()
print(self.token)
On the desktop version of my app I’ve been successfully using the following, again with an unverified Consent Screen, so I’m pretty sure that’s not the problem:
import googleapiclient.discovery
import google_auth_oauthlib.flow
import google.auth.transport.requests
scopes = ["https://www.googleapis.com/auth/youtube.readonly"]
youtube_api = googleapiclient.discovery.build("youtube", "v3", credentials=get_google_api_credentials(scopes))
results = youtube_api.channels().list(mine=True, part='contentDetails').execute()
where get_google_api_credentials()
is almost a direct copy of a sample from the googleapiclient
docs:
def get_google_api_credentials(scopes):
""" Returns credentials for given Google API scope(s) """
credentials = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if Path('token.pickle').is_file():
with open('token.pickle', 'rb') as token:
credentials = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
credentials.refresh(google.auth.transport.requests.Request())
else:
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file('credentials-windows.json', scopes)
credentials = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(credentials, token)
return credentials