I write a python script to do GET and PUT method in zendesk API and successfully get the data I wanted and do some updates to the tickets.
below method resulting this ticket number "6442" and put method is intended to remove the tags
from urllib.parse import urlencode
import json
import requests
# Set the credentials
credentials = 'some email', 'some password'
session = requests.Session()
session.auth = credentials
# Set the GET parameters
params_noreply_window = {
'query': 'type:ticket tags:test status<closed',
}
params_oustide_businesshour = {
'query': 'type:ticket tags:send_whatsapp_obh status:new',
}
url_search1 = 'https://propertypro.zendesk.com/api/v2/search.json?' + \
urlencode(params_noreply_window)
url_search2 = 'https://propertypro.zendesk.com/api/v2/search.json?' + \
urlencode(params_oustide_businesshour)
response_noreply_window = session.get(url_search1)
response_oustide_businesshour = session.get(url_search2)
# -----------------------------------------------------------------------------
if response_noreply_window.status_code != 200 | response_oustide_businesshour.status_code != 200:
print('Status 1:', response_noreply_window.status_code + 'Status 2:', response_oustide_businesshour.status_code,
'Problem with the request. Exiting.')
exit()
# Print the subject of each ticket in the results
data_noreply_window = response_noreply_window.json()
data_oustide_businesshour = response_oustide_businesshour.json()
# Ticket to update
# Create a list containing the values of the id field
# for each dictionary that is an element of the list data
id_merged1 = [result['id'] for result in data_noreply_window['results']]
print(type(id_merged1))
print(id_merged1)
id_merged2 = [result['id'] for result in data_oustide_businesshour['results']]
print(type(id_merged2))
print(id_merged2)
# Join value of list by using comma separated
id_merged1_joined = ','.join(map(str, id_merged1))
print(id_merged1_joined)
id_merged2_joined = ','.join(map(str, id_merged2))
print(id_merged2_joined)
# Package the data in a dictionary matching the expected JSON
data_comment1 = {"ticket":
{
"remove_tags": ["test"]
}
}
data_comment2 = {"ticket":
{
"remove_tags": ["send_whatsapp_obh"]
}
}
# Encode the data to create a JSON payload
payload1 = json.dumps(data_comment1)
payload2 = json.dumps(data_comment2)
print("**Start**")
# Set the request parameters
url_put_comments1 = 'https://propertypro.zendesk.com/api/v2/tickets/update_many.json?' +\
'ids=' + id_merged1_joined
url_put_comments2 = 'https://propertypro.zendesk.com/api/v2/tickets/update_many.json?' +\
'ids=' + id_merged2_joined
user = 'some email'
pwd = 'some password'
headers = {'content-type': 'application/json'}
# Do the HTTP put request
response_request_noreply = requests.put(url_put_comments1, data=payload1,
auth=(user, pwd), headers=headers)
response_request_obh = requests.put(url_put_comments2, data=payload2,
auth=(user, pwd), headers=headers)
# Check for HTTP codes other than 200
if response_request_noreply.status_code != 200 | response_request_obh.status_code != 200:
print('Status 1:', response_request_noreply.status_code +
'Status 1:', response_request_obh.status_code,
'Problem with the request. Exiting.')
exit()
# Report success
print('Successfully added comment to tickets')
However, after running my python code and do another GET method, the same ticket number still appears and I need to wait in random time to get the result I intend which is return 'null' since I have updated the ticket by using PUT method.
Can anyone explain me how does the Zendesk API works? and my apology for my incorrect sentences in explaining my concern.
Related
I have been attempting to solve this far too longer than id like to admit, I think the problem is how the data is being parsed with json and being interoperated via the API, as I do not have the same issue with the first function, but run into it with the second. Any help will be great.
import urllib, requests, json
def generateUserKey(username, password):
global devKey
return urllib.request.urlopen("https://pastebin.com/api/api_login.php",
urllib.parse.urlencode({"api_dev_key": devKey, "api_user_name": username, "api_user_password": password}).encode()).read()
def paste(userKey, text):
global devKey
datA = json.dumps({"api_dev_key": devKey, "api_paste_code": text, "api_user_key": userKey, "api_paste_name": "lol", "api_paste_format": "none", "api_paste_private": int(1), "api_paste_expire_date": "10M" })
resp = requests.post(url="https://pastebin.com/api/api_post.php", json=datA, data=datA)
print(resp.text)
key = generateUserKey(devKey, userName, passWord)
print(key)
paste(key, testString)
when ran I generate the following:
c0ce26a1c46d5fff3a254e519003ebb0
Bad API request, invalid api_dev_key
None
the dev key isnt invalid as its being used in the previous function to login and obtain a session key, so this is where I am stuck. Any help?
this could help:
import requests # see https://2.python-requests.org/en/master/
import json
def generateUserKey(data):
login = requests.post("https://pastebin.com/api/api_login.php", data=data)
print("Login status: ", login.status_code if login.status_code != 200 else "OK/200")
print("User token: ", login.text)
return login.text
def paste(data):
r = requests.post("https://pastebin.com/api/api_post.php", data)
print("Paste send: ", r.status_code if r.status_code != 200 else "OK/200")
print("Paste URL: ", r.text)
key = 'your key'
text = "hi"
t_title = "title of paste"
login_data = {
'api_dev_key': key,
'api_user_name': 'username',
'api_user_password': 'password'
}
data = {
'api_option': 'paste',
'api_dev_key': key,
'api_paste_code': text,
'api_paste_name': t_title,
'api_user_key': None,
# 'api_paste_expire_date': 'see_https://pastebin.com/api', # optional
# 'api_paste_private': 1, # 0 = public, 1 = unlisted, 2 = private
'api_user_key': generateUserKey(login_data)
# see_https://pastebin.com/api fro all the other arguments you can add
}
# if your data is already in json format, you can use json.dumps(data)
# data = json.dumps(data) # and now its a dict, and it can be feed to the requests.post
paste(data)
if you have any questions don't hesitate to ask
I'm brand new to python and api as well.
I'm trying to use a endpoint we have at work.
We have an API we are using a lot, we also have an UI. But using the UI we can only extract 10.000 records at the time.
There is no limit on the api.
I have found a small piece of code - but i need to add a nextpagetoken.
My code looks like this:
login_url = 'https://api.ubsend.io/v1/auth/login'
username = 'xxxxx'
password = 'xxxxx'
omitClaims = "true"
session = requests.Session()
session.headers['Accept'] = "application/json; charset=UTF-8"
response = session.post(
login_url,
json={'username': username, 'password': password},
headers={'VERSION': '3'},
)
response.raise_for_status()
response_data = response.json()
print(response_data)
This gives me the AccessToken.
Then I call:
getevents = 'https://api.ubsend.io/v1/reporting/shipments?'
data ={'client_id': 13490, 'created_after': '2020-05-01T00:00', 'created_before': '2021-05-02T00:00'} req.prepare_url(getevents, data)
events = requests.get(req.url, headers={'Authorization' : 'Bearer ' + response_data['accessToken'], Content-Type': 'application/json'})
events.json()
Which returns:
'nextPageToken': 'NjA4ZDc3YzNkMjBjODgyYjBhMWVkMTVkLDE2MTk4ODM5NzA3MDE='}
So I want to loop my script - until nextPageToken is blank ....
Any thoughts?
Edit thanks for the update. I think this might be the solution we're looking for. You might have to do some poking around to figure out exactly what the name of the page_token URL parameter should be.
has_next = True
getevents = 'https://api.ubsend.io/v1/reporting/shipments?'
token = None
while has_next:
data ={'client_id': 13490, 'created_after': '2020-05-01T00:00', 'created_before': '2021-05-02T00:00'}
if token:
# I don't know the proper name for this URL parameter.
data['page_token'] = token
req.prepare_url(getevents, data)
events = requests.get(req.url, headers={'Authorization' : 'Bearer ' + response_data['accessToken'], Content-Type: 'application/json'})
token = events.json().get('nextPageToken')
if not token:
has_next = False
I made a slight typo. It should be events.json().get('nextPageToken') I believe.
Let me know if this works.
I am trying to upload a pdf generated in Python as an attachment to a salesforce object using the simple_salesforce Python package. I have tried several different ways to accomplish this, but have had no luck so far. Here is the code
import base64
import json
from simple_salesforce import Salesforce
instance = ''
sessionId = sf.session_id
def pdf_encode(pdf_filename):
body = open(pdf_filename, 'rb') #open binary file in read mode
body = body.read()
body = base64.encodebytes(body)
body = pdf_encode('PDF_Report.pdf')
response = requests.post('https://%s.salesforce.com/services/data/v29.0/sobjects/Attachment/' % instance,
headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer %s' % sessionId },
data = json.dumps({
'ParentId': parent_id,
'Name': 'test.txt',
'body': body
})
)
I get this error.
TypeError: Object of type bytes is not JSON serializable
I have also tried to use
body = base64.encodebytes(body).decode('ascii')
in my code, but I can't get that to work either. I get the error
UnicodeError: encoding with 'idna' codec failed (UnicodeError: label empty or too long)
Any suggestions on how to upload a PDF in Python 3 into Salesforce as an attachment using simple_salesforce?
I was working on this and found a few resources to upload files. I created one for myself using that.
Below is the code that you can use for Python and have the file uploaded on Salesforce.
import requests
import base64
import json
params = {
"grant_type": "password",
"client_id": "Your_Client_Id",
"client_secret": "Your_Client_Secret",
"username": "YOUR_EMAIL#procureanalytics.com.pcsandbox", # The email you use to login
"password": "YOUR_PASSWORD+YOUR_SECURITY_TOKEN" # Concat your password and your security token
}
r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)
# if you connect to a Sandbox, use test.salesforce.com instead
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
print("Access Token:", access_token)
print("Instance URL", instance_url)
#######################################################################################
# Helper function
#######################################################################################
def sf_api_call(action, parameters = {}, method = 'get', data = {}):
"""
Helper function to make calls to Salesforce REST API.
Parameters: action (the URL), URL params, method (get, post or patch), data for POST/PATCH.
"""
headers = {
'Content-type': 'application/json',
'Accept-Encoding': 'gzip',
'Authorization': 'Bearer %s' % access_token
}
if method == 'get':
r = requests.request(method, instance_url+action, headers=headers, params=parameters, timeout=30)
elif method in ['post', 'patch']:
r = requests.request(method, instance_url+action, headers=headers, json=data, params=parameters, timeout=10)
else:
# other methods not implemented in this example
raise ValueError('Method should be get or post or patch.')
print('Debug: API %s call: %s' % (method, r.url) )
if r.status_code < 300:
if method=='patch':
return None
else:
return r.json()
else:
raise Exception('API error when calling %s : %s' % (r.url, r.content))
# Test connection
print(json.dumps(sf_api_call('/services/data/v40.0/query/', {
'q': 'SELECT Account.Name, Name, CloseDate from Opportunity where IsClosed = False order by CloseDate ASC LIMIT 1'
}), indent=2))
#######################################################################################
# File Upload from directory
#######################################################################################
# 1) Create a ContentVersion
path = "Folder_name\Sample_pdf.pdf"
with open(path, "rb") as f:
encoded_string = base64.b64encode(f.read()).decode("utf-8")
ContentVersion = sf_api_call('/services/data/v40.0/sobjects/ContentVersion', method="post", data={
'Title': 'Sample_pdf file',
'PathOnClient': path,
'VersionData': encoded_string,
})
ContentVersion_id = ContentVersion.get('id')
# 2) Get the ContentDocument id
ContentVersion = sf_api_call('/services/data/v40.0/sobjects/ContentVersion/%s' % ContentVersion_id)
ContentDocument_id = ContentVersion.get('ContentDocumentId')
# 3) Create a ContentDocumentLink
Id = "Abcd123" # This Id can be anything: Account_Id or Lead_Id or Opportunity_Id
ContentDocumentLink = sf_api_call('/services/data/v40.0/sobjects/ContentDocumentLink', method = 'post', data={
'ContentDocumentId': ContentDocument_id,
'LinkedEntityId': Id,
'ShareType': 'V'
})
How to use
Step 1:
Key in your email address and password here. Please note that the password here is a string of 'your password' and your 'security token'.
# Import libraries
import requests
import base64
import json
params = {
"grant_type": "password",
"client_id": "Your_Client_Id",
"client_secret": "Your_Client_Secret",
"username": "YOUR_EMAIL#procureanalytics.com.pcsandbox", # The email you use to login
"password": "YOUR_PASSWORD+YOUR_SECURITY_TOKEN" # Concat your password and your security token
}
r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)
# if you connect to a Sandbox, use test.salesforce.com instead
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
print("Access Token:", access_token)
print("Instance URL", instance_url)
You can get your security token on Salesforce through Account >> Settings >> Reset My Security Token.
You will receive an email from salesforce with your security token.
Step 2:
Choose appropriate link for request.post
For Sandbox environment:
r = requests.post("https://test.salesforce.com/services/oauth2/token", params=params)
For Production enviroment:
r = requests.post("https://login.salesforce.com/services/oauth2/token", params=params)
After your initial connection is ready, the output on the second cell should look something like this:
Access Token: !2864b793dbce2ad32c1ba7d71009ec84.b793dbce2ad32c1ba7d71009ec84
Instance URL https://your_company_name--pcsandbox.my.salesforce.com
Step 3:
Under the 'File upload from a directory' cell (Cell #5), specify your file path.
In my case, this is
# 1) Create a ContentVersion
path = "Folder_name\Sample_pdf.pdf"
with open(path, "rb") as f:
encoded_string = base64.b64encode(f.read()).decode("utf-8")
Step 4:
Under the same cell, mention the Id in which you would like to upload your file.
The sample code below is uploading a file on Accounts object for an account with Id: Abcd123
# 3) Create a ContentDocumentLink
Id = "Abcd123" # This Id can be anything: Account_Id or Lead_Id or Opportunity_Id
ContentDocumentLink = sf_api_call('/services/data/v40.0/sobjects/ContentDocumentLink', method = 'post', data={
'ContentDocumentId': ContentDocument_id,
'LinkedEntityId': Id,
'ShareType': 'V'
})
I grab the site-key using a some-what hardcoded method, but since the len is always the same it's ok.
After that I use the 2captcha API Documentation so that I can POST the key and GET the token for the captcha back. I face two major problems:
1) I always get the site-key wrong error, but the sitekey is correct according to their example (their sitekey is 40chars long and my sitekeys are 40 too)
2) I tried creating a POST function externally and trying it out seeing if it is a bug, but using the Py2Captcha documentation I always get the following error:
This is captcha key grabbing.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Captcha Key~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
url=driver.find_element_by_css_selector("iframe[role='presentation']").get_attribute('src')
print(url)
keygoogle = url[53:93]
print('Site Key = ', keygoogle)
This is the captcha key solving block:
answer = ""
answer_id = 0
api_key = '--------------------------------'
data_post = {'key': api_key, 'method': 'userrecaptcha', 'googlekey': keygoogle, "pageurl": mainurl}
response = requests.post(url = 'https://2captcha.com/in.php', data = data_post )
print(response)
print("Waiting for server response.")
for x in range(15):
time.sleep(1)
if x == 5:
print('Downloading info..')
elif x == 10:
print('Processing info..')
elif x == 14:
print('Solving captcha..')
data_request = {
'key': api_key,
'action': answer,
'id': answer_id,
}
requests.get(url ='https://2captcha.com/res.php', data=data_request)
print(answer)
def captcha():
google_key = keygoogle
url = mainurl
client = TwoCaptchaClient(client_key=api_key)
task = GoogleReCaptchaV2Task(googlekey=google_key, pageurl=mainurl)
job = client.create_task(task)
token = job.get_solution_response()
return token
print(captcha())
What I haven't included is the part where the token gets posted into the answer field, I am not sure how to do that yet but I will find a way for sure!
EDIT:
This is the value I get from printing this:
response = requests.post(url = 'https://2captcha.com/in.php', data = data_post )
And this is the value I get from print('Site Key = ', keygoogle)
Site Key = Lc3HAsUAAAAACsN7CgY9MMVxo2M09n_e4heJEiZ&
This is my way of grabbing the correct key:
url=driver.find_element_by_css_selector("iframe[role='presentation']").get_attribute('src')
keygoogle = url[52:92]
And this is my POST function:
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Captcha Solve~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
answer = ""
answer_id = 0
data_post = {'key': api_key, 'method': 'userrecaptcha', 'googlekey': keygoogle, "pageurl": mainurl}
response = requests.post(url = 'https://2captcha.com/in.php', data = data_post )
response = response.text[3:]
print("Waiting for server response.")
for x in range(30):
time.sleep(1)
if x == 8:
print('Downloading info..')
elif x == 15:
print('Processing info..')
data_request = {'key': api_key,'id': int(response),'action': 'get'}
response = requests.get(url='https://2captcha.com/res.php', params=data_request)
token = response.text.split('|')[0]
while response.text == 'CAPCHA_NOT_READY':
print('Waiting for Capcha..')
time.sleep(5)
response = requests.get(url='https://2captcha.com/res.php', params=data_request)
token = response
print(token)
The & on the end of that sitekey definitely isn't supposed to be there. Use a regex instead of what you're doing there with the indexes.
Okay so I'm using code very similar to this (https://gist.github.com/metadaddy-sfdc/1374762)
to get authentication token and do simple query's using the libur2 for the rest api in python for a sales force database, but when I tried to follow the instructions which were given in this answer How to make HTTP DELETE method using urllib2?,
I cannot get it to work so that I can use delete, both codes use liburl but they seem to be in different format, so that I don't know how to apply the solution offered on stack exchange, to my code, as you can tell I am a beginner so any help would be greatly appreciated
edit:
here is the code I'm using with keys/passwords blanked
import urllib
import urllib2
import json
import pprint
import re
import subprocess
def authorise():
consumer_key = '**********************'
consumer_secret = '**************'
username = '***********'
password = '*****************'
login_server = 'https://login.salesforce.com'
token_url = login_server+'/services/oauth2/token'
params = urllib.urlencode({
'grant_type': 'password',
'client_id': consumer_key,
'client_secret': consumer_secret,
'username': username,
'password': password
})
data = urllib2.urlopen(token_url, params).read()
oauth = json.loads(data)
return oauth
def country_id_query(params):
query_url = oauth['instance_url']+'/services/data/v23.0/query?%s' % params
headers = {
'Authorization': 'OAuth '+oauth['access_token']
}
req = urllib2.Request(query_url, None, headers)
data = urllib2.urlopen(req).read()
result = json.loads(data)
id = result['records'][0]['Id']
return id
oauth = authorise()
token = oauth['access_token']
print "\ntoken is = " + token
params = urllib.urlencode({
'q': 'SELECT id from Country__c WHERE name = \'A New Found Land\''
})
id = country_id_query(params)
print "\nCountry id is "+id + "\n"
I am looking to find out what I need to add to this to get DELETE working
Okay, found the solution to above for anyone with a similar problem:
def delete_country(id):
query_url = oauth['instance_url']+'/services/data/v23.0/sobjects/Country__c/%s' % id + '/'
headers = {
'Authorization': 'OAuth '+oauth['access_token']
}
opener = urllib2.build_opener(urllib2.HTTPHandler)
req = urllib2.Request(query_url, None, headers)
req.get_method = lambda: 'DELETE' # creates the delete method
url = urllib2.urlopen(req) # deletes database item