How to subscribe to changes on Google Drive using watch - google-drive-api

I am quite stuck in trying to subscribe to changes on a google drive folder. My python3 code is as follows:
SCOPES = 'https://www.googleapis.com/auth/drive.readonly'
store = file.Storage('storage.json')
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets('client_id.json', SCOPES)
credentials = tools.run_flow(flow, store)
# This starts the authorization process
DRIVE = discovery.build('drive', 'v3', http=credentials.authorize(Http()))
try:
with open('saved_start_page_token.json') as json_data:
d = json.load(json_data)
try:
saved_start_page_token = d["startPageToken"]
except KeyError:
saved_start_page_token = d["newStartPageToken"]
print("Using saved token: %s" % saved_start_page_token)
except FileNotFoundError:
response = DRIVE.changes().getStartPageToken().execute()
with open("saved_start_page_token.json", "w") as token:
json.dump(response, token)
saved_start_page_token = response.get('startPageToken')
print('Start token: %s' % saved_start_page_token)
body = dict()
body["kind"] = "api#channel"
body["id"] = str(uuid.uuid4()) # TODO: do I have to do something with this channel id?
print(body["id"])
body["resourceId"] = 'web_hook'
body["resourceUri"] = 'https://meg-wm-it-change.appspot.com/notifications/'
json_body = json.dumps(body)
print(json_body)
request = DRIVE.changes().watch(pageToken = saved_start_page_token, body=json_body)
response = request.execute()
return response.body
Except this throws the error
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/drive/v3/changes/watch?pageToken=163958&alt=json returned "entity.resource">
Which I can't quite decipher. I'm sure my issue will be not understanding the documentation, (ie, I don't understand whether the params go versus the body of this request, and can't find any code samples) but any help would be appreciated!

I am going to post the answer I found to my own question in the event that anyone else wanders here:
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive']
def auth():
creds = 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 os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
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()
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
return creds
def subscribe_changes(service):
channel_id = str(uuid.uuid4())
body = {
"id": channel_id,
"type": "web_hook",
"address": COOL_REGISTERED_DOMAIN
}
response = service.changes().watch(body=body, pageToken = get_page_token(service)).execute()
ts = response['expiration']
print(dateparser.parse(ts))
print(response)
return channel_id
def main():
creds = auth()
service = build('drive', 'v3', credentials=creds)
subscribe_changes(service)

Related

Unable to stream data from twitter using Pyspark

I am new to Twitter stream analytics
I was unable to use the tweepy streaming as there was a change in the API version 2.0. So I am currently trying to stream it using a bearer token.
I am facing two issues:
Getting error- The content for this response was already consumed
How to send the JSON response to the Spark stream
I am streaming the JSON response by using stream=True
Any pointers/alternatives would be great!
import requests
import os
import json
bearer_token = 'your bearer token'
query = "fifa"
tweet_fields = "tweet.fields=id,created_at,text"
expansions = "expansions=author_id"
headers = {"Authorization": "Bearer {}".format(bearer_token)}
def create_url(query, tweet_fields, expansions):
url = "https://api.twitter.com/2/tweets/search/recent?query={}&{}".format(
query, tweet_fields, expansions
)
return url
def bearer_oauth(r):
"""
Method required by bearer token authentication.
"""
r.headers["Authorization"] = f"Bearer {bearer_token}"
r.headers["User-Agent"] = "v2SampledStreamPython"
return r
def connect_to_endpoint(url):
response = requests.request("GET", url, auth=bearer_oauth, stream=True)
#print(response.status_code)
for response_line in response.iter_lines():
if response_line:
json_response = json.loads(response_line)
t=json.dumps(json_response, indent=4, sort_keys=True)
if response.status_code != 200:
raise Exception(
"Request returned an error: {} {}".format(
response.status_code, response.text
)
)
def main():
url = create_url(query, tweet_fields, expansions)
timeout = 0
while True:
connect_to_endpoint(url)
timeout += 1
if __name__ == "__main__":
main()

Authentication behavior in cloud functions different from that in colab

I have a google project service account from which I got a json file. The following code works on colab:
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import json
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
# The ID and range of a sample spreadsheet.
SAMPLE_SPREADSHEET_ID = 'google_sheets_id'
SAMPLE_RANGE_NAME = 'range'
creds = None
creds = service_account.Credentials.from_service_account_info(credentials_json, scopes=SCOPES)
service = build('sheets', 'v4', credentials=creds)
values = [['planta','hshshsjh#gmail.com']]
body = {'values': values }
result = service.spreadsheets().values().append(spreadsheetId=SAMPLE_SPREADSHEET_ID,range=SAMPLE_RANGE_NAME,body=body, valueInputOption="USER_ENTERED").execute()
but not in a cloud function:
CREDENTIALS_INFO = os.environ.get("CREDENTIALS_INFO")
SCOPES = os.environ.get("SCOPES")
SPREADSHEET_ID = os.environ.get("SPREADSHEET_ID")
RANGE_NAME = os.environ.get("RANGE_NAME")
VALUE_INPUT_OPTION = os.environ.get("VALUE_INPUT_OPTION")
creds = service_account.Credentials.from_service_account_info(json.loads(CREDENTIALS_INFO), scopes=SCOPES)
service = build('sheets', 'v4', credentials=creds)
if 'planta' in request_json['queryResult']['parameters']:
values = [['planta',mail]]
body = {"values":values}
service.spreadsheets().values().append(spreadsheetId=SPREADSHEET_ID,range=RANGE_NAME,body=body, valueInputOption=VALUE_INPUT_OPTION).execute()
I get the following error:
File "/layers/google.python.pip/pip/lib/python3.10/site-packages/google/oauth2/_client.py", line 220, in jwt_grant
access_token = response_data["access_token"]
KeyError: 'access_token'
What could be happening?

Csrf token is missing problem in my flask route

Csrf token missing problem in my flask route i mention my error please review my code and find solution because i am new to flask
My app.py file:
#app.route('/register', methods=['GET', 'POST'])
#csrf.exempt
def register():
if request.method == 'POST':
form = RegisterForm()
if form.validate_on_submit():
name = request.form['name']
email = request.form['email']
gender = request.form['gender']
username = request.form['username']
password = sha256_crypt.encrypt(str(request.form['password']))
user = User(name=name, email=email, gender=gender, username=username, password=password)
db.session.add(user)
db.session.commit()
response = {"succcess":"User registered successfully and now you can login"}
return jsonify(response)
elif not form.validate_on_submit():
response = {"errors":form.errors}
return jsonify(response)
My error in response:
{
"errors": {
"csrf_token": [
"The CSRF token is missing."
]
}
}
How i solve this issue I am new to flask web framework
Csrf token missing problem in my flask route i mention my error please review my code and find solution because i am new to flask

Get the token and send it as value for Authorization header for the rest of the steps

After I get a token from a Post request as shown below:
{ "access_token": "12345", "expires_in": 3600, "token_type": "Bearer" }
I want to use this token in different TestSteps Headers values.
For example I have to make a GET request after I received this token and it have in the header -> Authentification : Bearer + token_value.
So can I write a GroovyScript or something to make this automatically? I'm using ReadyApi.
Regards,
Adrian
Add Script Assertion for the same step where you receive the mentioned response:
Script Assertion this fetches the values from response and creates a project property and set the retrieved value.
//Check if the response is empty or null
assert context.response, "Response is null or empty"
def json = new groovy.json.JsonSlurper().parseText(context.response)
def token = "${json.token_type} ${json.access_token}" as String
log.info "Token will be: ${token}"
//Assing the value at project level property TOKEN
context.testCase.testSuite.project.setPropertyValue('TOKEN', token)
Now the value needs to be set as header to each outgoing request dynamically. i.e., Add Authorization header and its value for the SOAP or REST request type steps. For this, Events feature is going to be used.
Add a SubmitListener.beforeSubmit event and add the below script into it. Please follow the comments inline.
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestRequestStep
import com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep
//Please edit the header name as you wanted
def headerName = 'Authorization'
//a method which sets the headers
def setHttpHeaders(def headers) {
def step = context.getProperty("wsdlRequest").testStep
if (step instanceof RestTestRequestStep || step instanceof WsdlTestRequestStep) {
def currentRequest = step.httpRequest
def existingHeaders = currentRequest.requestHeaders
headers.each {
existingHeaders[it.key] = it.value
}
currentRequest.requestHeaders = existingHeaders
} else {
log.info 'not adding headers to the current step as it is not request type step'
}
}
//read the token from project properties
def token = context.expand('${#Project#TOKEN}')
//assert the value of token
assert token, "Token is null or empty"
//UPDATE from the comment to add the header to next request
if (token) {
def headerValue = [(token)]
def headers = [(headerName) : (headerValue)]
setHttpHeaders(headers)
}
import groovy.json.JsonSlurper
import groovy.json.*
def tokens=testRunner.runStepByname("Token")
def response = context.expand( '${Token#Response}' )
def JsonSlurperjsonSlurper = newJsonSlurper()
def Objectresult = jsonSlurper.parseText(response)
def access_token= result.access_token
def authorization = "Bearer "+access_token
testRunner.testCase.setPropertyValue("access_token", authorization)

Sending Onesignal/gamethrive push by JSON network request

I am trying to send a JSON request to send a push notification using the following code but I get an error message for the network response saying "app_id not found". I am using Corona but this shouldnt matter as long as JSON format is right.
local json = require "json"
local function networkListener( event )
if ( event.isError ) then
print( "Network error!" )
else
print ( "RESPONSE: " .. event.response )
end
end
headers = {}
headers["app_id"] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
headers["Authorization"] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
headers["Content-Type"] = "application/json"
local params = {}
commands_json =
{
["contents"] = "English Message"
}
postData = json.encode(commands_json)
local params = {}
params.header = headers
params.body = postData
network.request( "https://onesignal.com/api/v1/notifications","POST",networkListener,params)
I could work it out.
function SendJson(url, action, in_json, callback)
local json = require ( "json" )
local headers = {}
headers["Content-Type"] = "application/json"
headers["Accept-Language"] = "en-US"
headers["Authorization"] = "Basic 12121321313123" -- put your Rest API
local params = {}
params.headers = headers
params.body = json.encode( in_json )
network.request ( url, action, callback, params )
end
local function networkListener( event )
if ( event.isError ) then
print( "Network error!")
else
print ( "RESPONSE: " .. event.response )
end
end
local jsonToSend = {["app_id"] = "aaaaaa-222-222-33-3333333333", --put yours App ID
["contents"] = {["en"] = "George challenged you to beat his score!"},
["included_segments"] = "All",
["isAndroid"] = true,
["isIos"] = true,}
--["include_player_ids"] = ["(RECIPIENT_PLAYER_ID_HERE)"]}
SendJson("https://gamethrive.com/api/v1/notifications", "POST", jsonToSend, networkListener)
Do you have both Android and Apple setup on your app on the OneSignal dashboard? Platforms(isAndroid and isIos) are not required parameters when you use include_player_ids.
Also make sure you don't use the Authorization header in your production app as someone can easily disassemble your app and get the REST API key. When you use the include_player_ids field the Authorization header is not required.
See the OneSignal create notification POST call for the full documentation.
Also I recommend you switch to using "https://onesignal.com/api/v1/notifications" as the URL in your code to save on redirects.