ServiceNow SOAP API close ticket with python - python

I'm working on connecting a python script to a ServiceNow ticketing environment. Thankfully, ServiceNow has documentation on how to create a ticket from a python script, see documentation here:
http://wiki.servicenow.com/index.php?title=Python_Web_Services_Client_Examples#gsc.tab=0
Here's the script I'm using to create a ticket:
#!/usr/bin/python
from SOAPpy import SOAPProxy
import sys
def createincident(params_dict):
# instance to send to
instance='demo'
# username/password
username='itil'
password='itil'
# proxy - NOTE: ALWAYS use https://INSTANCE.service-now.com, not https://www.service-now.com/INSTANCE for web services URL from now on!
proxy = 'https://%s:%s#%s.service-now.com/incident.do?SOAP' % (username, password, instance)
namespace = 'http://www.service-now.com/'
server = SOAPProxy(proxy, namespace)
# uncomment these for LOTS of debugging output
#server.config.dumpHeadersIn = 1
#server.config.dumpHeadersOut = 1
#server.config.dumpSOAPOut = 1
#server.config.dumpSOAPIn = 1
response = server.insert(impact=int(params_dict['impact']), urgency=int(params_dict['urgency']), priority=int(params_dict['priority']), category=params_dict['category'], location=params_dict['location'], caller_id=params_dict['user'], assignment_group=params_dict['assignment_group'], assigned_to=params_dict['assigned_to'], short_description=params_dict['short_description'], comments=params_dict['comments'])
return response
values = {'impact': '1', 'urgency': '1', 'priority': '1', 'category': 'High',
'location': 'San Diego', 'user': 'fred.luddy#yourcompany.com',
'assignment_group': 'Technical Support', 'assigned_to': 'David Loo',
'short_description': 'An incident created using python, SOAPpy, and web
services.', 'comments': 'This a test making an incident with python.\nIsn\'t
life wonderful?'}
new_incident_sysid=createincident(values)
print "Returned sysid: "+repr(new_incident_sysid)
However, I cannot find any good documentation on the process to resolve the ticket that I just created using the API. When I run the above script, I get the ticket number as well as the sys_id.
Any help would be appreciated.
Thanks.

Apparently thats an old request, but i landed here searching, and apprently 400 other people too, so here is my solution :
Use the server.update(sys_id="...",state="..",...) to modify your record and set the right values to "resolve" it.
For this method only the sys_id parameter is mandatory, it's up to you for the other fields of your form.
P.S. : you can find the API here - https://.service-now.com/incident.do?WSDL

Related

Django back-end scripts scheduling

I'm building a website with Django and among other things I want to display the latest news about a certain topic. I have a python script in the back-end that I would like to program to retrieve the latest news once every 1 hour for example. In the meantime I want to be able to display the most recently retrieved news. I'm doing this in order to avoid that the script is being activated every time someone opens my website.
My script is in news.py:
import pprint
import requests
import datetime
import pandas as pd
import dateutil.parser
secret = "********"
url = 'https://newsapi.org/v2/everything?'
quote = 'Amazon'
parameters1 = {
'q': quote,
'pageSize': 100,
'sortby': 'publishedAt',
'apiKey': secret,
}
response1 = requests.get(url, params=parameters1)
response_json1 = response1.json()
text_combined1 = []
for i in response_json1['articles']:
if i['content'] != None:
case = {'Source': i['source']['name'], 'Title': i['title'], 'url': i['url'],
'Published on:': dateutil.parser.parse(i['publishedAt']).strftime('%Y-%m-%d'), 'Image': i['urlToImage']}
text_combined1.append(case)
data_amazon = pd.DataFrame.from_dict(text_combined1)
news1 = data_amazon.iloc[0]
news2 = data_amazon.iloc[1]
news3 = data_amazon.iloc[2]
My views.py looks like this:
from django.shortcuts import render
from .news import *
def dashboard(request):
content = {'data': data, 'news1': news1, 'news2': news2, 'news3': news3}
return render(request, 'dashboard.html',
content)
I'm new to web development but my understanding as of now is that every time someone sends a request to my webpage that script would be run, which would result in delay in the display of the news and most likely access denial to the news.api due to too many requests.
Thank you in advance!
A good way to do this is with Celery. It will let you schedule tasks in Django.
You can read more about it here, and see some other options as well.
Set up a scheduled job?

How to post an adset to Facebook Marketing api using python

I am trying to post an adset to the facebook marketing api using the python sdk.
I am getting this error.
FacebookBadObjectError: This AdSet object was already created.
From this line:
adset.remote_create(params={'status': 'PAUSED'})
Here is the function:
adset = AdSet(campaign_result["id"])
adset.update({
'name': 'test adset ex_2',
'campaign_id': campaign_result["id"],
'daily_budget': 150,
'billing_event': 'IMPRESSIONS',
'optimization_goal': 'REACH',
'bid_amount': 10,
'targeting': {'geo_locations': {'countries': ['US']},
'publisher_platforms': ['facebook']},
'start_time': start_time,
'end_time': end_time
})
adset.remote_create(params={'status': 'PAUSED'})
The documentation does not cover this. I am following this guide: https://medium.com/#gokhang1327/publishing-facebook-ads-with-python-step-by-step-5c2a98ee4d58
With this code:
https://github.com/gokhangerdan/publish_facebook_ads/blob/master/script.py
My parameters work on the graph api explorer.
How can i post an adset in python?
This is slightly different than how you were going about it, but I have found it to be much easier to perform all "create" actions at the AdAccount class level, regardless of whether you're creating a campaign, ad set, or ad. This is a function I created for creating new ad sets, assuming the campaign you want to create it in already exists:
my_adaccount = AdAccount([INSERT AD ACCOUNT ID HERE])
def create_ad_set(name, campaign_id, optimization_goal, status, daily_budget, billing_event, targeting, bid_strategy):
params = {
'name': name,
'campaign_id': campaign_id,
'optimization_goal': optimization_goal,
'status': status,
'daily_budget': daily_budget,
'billing_event': billing_event,
'targeting': targeting,
'bid_strategy': bid_strategy
}
response = my_adaccount.create_ad_set(params=params)
print(response)
newest_adset = response['id']
After lots of trial and error, I determined that those are all the required parameters to successfully create an ad set. You can obviously edit them them or add more however you like within the function arguments. Your options can be found here for easy reference.

Jira API Assignee not populating with "name" anymore, instead needs "accoundId"

I'm working with Python 3.x
Previously, I had a function to create tickets that looks like this
def jira_incident(jira_subject, jira_description):
user = "username"
apikey = 'apikey'
server = 'https://serverName.atlassian.net'
options = {
'server': server,
'verify': False
}
issue_dict = {
'project': {'key': 'project_name'},
'summary': str(jira_subject),
'description': str(jira_description),
'issuetype': {'name': 'Incident'},
'assignee': {'name': my_username},
'priority': {'name': 'Low'},
'customfield_10125':
{'value': 'Application Ops'}
}
jira = JIRA(options, basic_auth=(user, apikey))
new_issue = jira.create_issue(fields=issue_dict)
return new_issue
my_username is a global variable that's used for other things as well.
Anyway, the assignee is no longer working as of about 2 days ago. I did some googling and found that it now needs the accountId instead of the name, I can get this via the web UI by leaving a comment as #'ing someone in a comment. As a temporary solution I've populated a dictionary to reference (and that works), however I'd like to make this more dynamic for future proofing the script.
'assignee': {'accountId': jira_dict[my_username]},
I can't seem to really find any documentation on looking up the accountId from the name, and I figured I'd go ahead and ask the community to see if anyone else has run into/solved this issue.
I was thinking about just writing a new function that performs this query for me, then returns the accountId.
EDIT
I did find this:
import requests
from requests.auth import HTTPBasicAuth
import json
url = "/rest/api/3/user/bulk/migration"
auth = HTTPBasicAuth("email#example.com", "<api_token>")
headers = {
"Accept": "application/json"
}
response = requests.request(
"GET",
url,
headers=headers,
auth=auth
)
print(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(",", ": ")))
However it 404's on me, I add the server address to the beginning of the url, and replace user, with the username in question.
Okay, I found a solution, it's not an elegant solution, but it does exactly what I need it to. So here is the new function:
def jira_account_id_from_username(username):
r = requests.get('https://serverName.atlassian.net/rest/api/3/user?username=' + username, auth=("username",api_key), verify=False)
value = re.search('"accountId":"(.*?)",', str(r.text)).group(1)
return value
I strongly encourage you to not rely on the username anymore. The endpoint you are using is deprecated, see also https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-user-privacy-api-migration-guide/.
The "new" or probably better way is to use the /user/search endpoint as described here: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-user-search-get There you can define a query that is matching against certain properties of a user (displayName or emailAddress), or search for the accountId if you already have it. Therefore, if you are linking users from the cloud to some other "user directory" (or just a scripts where you have stored some usernames), replace it by using either email address or accountId so you can properly link your users.

Facebook API | facebook.GraphAPIError: (#100) Only owners of the URL have the ability to specify the picture

Hi i'm owner of a facebook page, inside it i would like to post some contents taken from web site.
for example i want to post an item of amazon like this:
https://www.amazon.it/dp/....
if i post manually the url i can see correctly the preview and all details related to the item but programmatically i can't
i am using python 3.6 and actually i have this script:
import facebook
graph = facebook.GraphAPI(access_token=token)
attachment = {
'name': 'Link name',
'link': 'https://www.amazon.it/dp/...',
'caption': 'Check out this example',
'description': 'This is a longer description of the attachment',
'picture': 'url_of_the_image'
}
graph.put_wall_post(message='Check this out...', attachment=attachment, profile_id='my_page_id')
when i launch the script it raise the exception
raise GraphAPIError(result)
facebook.GraphAPIError: (#100) Only owners of the URL have the ability to specify the picture, name, thumbnail or description params.
I googled for it and i found similar issues solved registering the domain in the Business manager dashboard, i tried it but it says "Amazon domain already registered" (obviously)
What can i do?
You do not own www.amazon.it (i assume), so you cannot use your own picture or your own Open Graph data. Dynamic data is not possible anymore anyway, you need to use Open Graph tags in the source of the shared URLs instead. They get used automatically.

Updating records with Python 3 through API on Rails 4 application

I'm working on a Rails 4 / mongoid application which needs to expose APIs for other applications and scripts. I need to be able to update documents in one of the models through an API with Python 3 script. I'm a bit fresh with Python hence asking for help here.
I already found out how to query Rails APIs with Python 3 and urllib but struggling with updates. I was trying to go through Python 3.5 docs for urllib2 but struggling to apply this to my script.
What goes to data and how to add authentication token to headers, which in curl would look something like this
-H 'Authorization:Token token="xxxxxxxxxxxxxxxx"'
-X POST -d "name=A60E001&status=changed"
I would greatly appreciate if somebody explained how to, for example, update status based on name (name is not unique yet but will be). My biggest challenge is the Python side. Once I have the data in params on Rails side I think I can handle it. I think.
I included my model and update action from the controller below.
app/models/experiment.rb
class Experiment
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :status, type:String
end
app/controllers/api/v1/experiments_controller.rb
module Api
module V1
class ExperimentsController < ActionController::Base
before_filter :restrict_access
...
def update
respond_to do |format|
if #expt_proc.update(expt_proc_params)
format.json { render :show, status: :ok, location: #expt_proc }
else
format.json { render json: #expt_proc.errors, status: :unprocessable_entity }
end
end
end
...
private
def restrict_access
authenticate_or_request_with_http_token do |token, options|
ApiKey.where(access_token: token).exists?
end
end
...
I figured out who to send a PATCH request with Python 3 and update the the record's status by name.
Thanks to this post found out about requests module. I used requests.patch to update the record and it works great.
python code
import requests
import json
url = 'http://0.0.0.0:3000/api/v1/update_expt_queue.json'
payload = {'expt_name' : 'myExperiment1', 'status' : 'finished' }
r = requests.patch(url, payload)
There are two problems remaining:
How to add headers to this request which would allow me to go through token based authentication. At the moment it's disabled. request.patch only takes 2 parameters, it doesn't take headers parameter.
How to access the JSON which is sent in response by Rails API.

Categories