How can I access 37 signals Highrise's API with Python? Found wrappers for PHP/Ruby, but not Python. I'm writing my own now, anyone have advice on getting over the first hurdle of authentication with Python?
I wrote (am writing, really) a Highrise API wrapper for Python. It uses Python objects for each of the Highrise classes and work a lot like the Django ORM:
>>> from pyrise import *
>>> Highrise.server('my-server')
>>> Highrise.auth('api-key-goes-here')
>>> p = Person()
>>> p.first_name = 'Joe'
>>> p.last_name = 'Schmoe'
>>> p.save()
You can get the source from GitHub: https://github.com/feedmagnet/pyrise
Or install it from PyPI:
$ sudo pip install pyrise
I was just tackling this problem when I stumbled onto your question. Here is what I have hacked together so far. Its not pretty (yet) but it works. I don't know Pycurl and after looking at it for a while I went back to urllib2. Highrise uses Basic Authentication so you don't have to use CURL you can use urllib2. You just have to go through all the Pword Manager steps. The output is a long XML file of either all the companies or the people depending on which URL you insert. If you wanted just one person you could do something like 'http....../people/123.xml' or 'http....../people/123-fname-lname.xml' (like you see in the url when you actually go to a contact in highrise with the .xml added).
import ullib2
PEOPLEurl = 'http://yourcompany.highrisehq.com/people.xml' #get all the people
# or
COMPANYurl = 'http://yourcompany.highrisehq.com/company.xml' #get all companies
token = '12345abcd' #your token
password = 'X'
passmanager = urllib2.HTTPPasswordMgrWithDefaultRealm()
passmanager.add_password(None, PEOPLEurl, token, password)
authhandler = urllib2.HTTPBasicAuthHandler(passmanager)
opener = urllib2.build_opener(authhandler)
urllib2.install_opener(opener)
page = urllib2.urlopen(PEOPLEurl).read()
print page #this will dump out all the people contacts in highrise
Any feedback or suggestions on this code would be helpful!
See here on how to do basic authentication. Also IIRC urllib supports http://user:password#example.com URLs.
i was just looking to the php code of one of the php API wrappers and i see that they use curl ; so have you looked to pycurl ??
about the authentication here is an example that you can start with (it's not tested)...
import pycurl
def on_receive(data):
# process your data here
pass
def connetion(url, token)
conn = pycurl.Curl()
# Set Token.
conn.setopt(pycurl.USERPWD, "%s:x" % (token,))
# the format TOKEN:x i get it from the PHP wrapper because usually the
# format should be USER:PASSWD so here i think they just use a token as
# a USERname and they set the password to 'x'.
conn.setopt(pycurl.URL, url)
# Set the XML data to POST data.
conn.setopt(pycurl.POSTFIELDS, XML_DATA)
# Add SSL.
conn.setopt(pycurl.SSL_VERIFYPEER, 0)
conn.setopt(pycurl.SSL_VERIFYHOST, 0)
# Set function that will be called as soon as the data is received.
conn.setopt(pycurl.WRITEFUNCTION, on_receive)
# Perform the data transfer.
conn.perform()
if __name__ == '__main__':
connection("http://yourcompany.highrisehq.com", your_token)
Related
I'm trying to use python to connect to Salesforce Bulk API. However, I don't want to test my code on the real salesforce. I want to test with my sandbox. However, I don't know how to connect to sandbox only... I've tried to add sandbox=True but it doesn't work...
import salesforce_bulk
bulk=salesforce_bulk.SalesforceBulk(username="username",password="password")
The advice here may be a bit deprecated. I was able to get the bulk uploads working by combining the Salesforce and SalesforceBulk libraries. Note the domain that I am passing to the api as well the sand_box name that needs to be appended to the username.
from simple_salesforce import Salesforce
from salesforce_bulk import SalesforceBulk
import json
from salesforce_bulk.util import IteratorBytesIO
from urllib.parse import urlparse
USER = "user#domain.com.<sandbox_name>"
PASS = "pass"
SEC_TOKEN = "token"
DOMAIN = "<domain>--<sandbox_name>.<instance>.my"
sf = Salesforce(username=USER, password=PASS, security_token=SEC_TOKEN, domain=DOMAIN)
bulk = SalesforceBulk(sessionId=sf.session_id, host=sf.sf_instance)
job = bulk.create_query_job("table", contentType='JSON')
batch = bulk.query(job, "select Id,LastName from table limit 5000")
bulk.close_job(job)
while not bulk.is_batch_done(batch):
sleep(10)
for result in bulk.get_all_results_for_query_batch(batch):
result = json.load(IteratorBytesIO(result))
for row in result:
print(row)
Old question but I had the same problem today, so maybe this will help someone.
This is a complete hack, but it works - probably a better hack would be to do this using salesforce-oauth-request (which does have a "sandbox=True" option), but I was logging in via beatbox anyway, so tried this first.
Gist is you log in to the sandbox using beatbox (which lets you specify your serverUrl) and then use that sessionId and instance_url to log in through salesforce_bulk.
import beatbox
from salesforce_bulk import SalesforceBulk
# log in to sandbox using beatbox
service = beatbox.PythonClient()
service.serverUrl = 'https://test.salesforce.com/services/Soap/u/20.0'
user = 'user#user.com'
password = 'secret'
token = '12345'
service.login(user, password+token)
# the _Client_serverUrl has the instance url + some
# SOAP stuff, so we need to strip that off
groups = service._Client__serverUrl.split('/')
instance_url = '/'.join(groups[:3])
# now we can use the instance_url and sessionId to
# log into Salesforce through SalesforceBulk
bulk = sfdc_bulk_connect(instance_url, service.sessionId)
Have you check the package is install
This library will use the salesforce-oauth-request package (which you must install) to run the Salesforce OAUTH2 Web flow and return an access token.
And the password did you have token or not ?
I have made a simple web form in Google app engine where I have added a recaptcha component.
The component is showing up on my web page. But i have no idea how to make the api call.
my code is;
def post(self):
challenge = self.request.get('recaptcha_challenge_field')
response = self.request.get('recaptcha_response_field')
remoteip = os.environ['REMOTE_ADDR']
private_key = 'xxx'
cResponse = self.request.submit(http://www.google.com/recaptcha/api/verify?privatekey="private_key"&remoteip="remoteip"&challenge="challenge"&response="response")
if cResponse.is_valid:
# response was valid
# other stuff goes here
pass
else:
error = cResponse.error_code
its pretty clear that my api call is completely wrong but i have no idea how to make it.
The examples i have seen use the plugin.
Use the URL Fetch API documented here, the first example in the linked page should be suitable for your needs.
Notice that url fetches have a quota and are billable.
I'm writing a command-line application that accesses linkedin. I'm using the python-linkedin API.
Things work as I expected, but I have a really big gripe about the authentication process. Currently, I need to:
Start my application and wait for it to print an authentication URL
Go to that URL with my browser
Give my blessing for the application and wait for it to redirect me to a URL
Extract the access token from the URL
Input that access token into my application
Do what I need to do with linkedin
I don't like doing steps 2 to 5 manually so I would like to automate them. What I was thinking of doing was:
Use a headless client like mechanize to access the URL from step 1 above
Scrape the screen and give my blessing automatically (may be required to input username and password -- I know these, so it's OK)
Wait to be redirected and grab the redirection URL
Extract the token from the URL
PROFIT!
Question time:
Looking around, this guy right here on SO tried to do something similar but was told that it's impossible. Why?
Then, this guy here does it in Jython and HtmlUnit. Should be possible with straight Python and mechanize, right?
Finally, has anybody seen a solution with straight Python and mechanize (or any other headless browser alternative)? I don't want to reinvent the wheel, but will code it up if necessary.
EDIT:
Code to initialize tokens (using the approach of the accepted answer):
api = linkedin.LinkedIn(KEY, SECRET, RETURN_URL)
result = api.request_token()
if not result:
print 'Initialization error:', api.get_error()
return
print 'Go to URL:', api.get_authorize_url()
print 'Enter verifier: ',
verifier = sys.stdin.readline().strip()
if not result:
print 'Initialization error:', api.get_error()
return
result = api.access_token(verifier=verifier)
if not result:
print 'Initialization error:', api.get_error()
return
fin = open('tokens.pickle', 'w')
for t in (api._request_token, api._request_token_secret,
api._access_token, api._access_token_secret ):
pickle.dump(t, fin)
fin.close()
print 'Initialization complete.'
Code to use tokens:
api = linkedin.LinkedIn(KEY, SECRET, RETURN_URL)
tokens = tokens_fname()
try:
fin = open(tokens)
api._request_token = pickle.load(fin)
api._request_token_secret = pickle.load(fin)
api._access_token = pickle.load(fin)
api._access_token_secret = pickle.load(fin)
except IOError, ioe:
print ioe
print 'Please run `python init_tokens.py\' first'
return
profiles = api.get_search({ 'name' : name })
As you are planning on authorizing yourself just once, and then making calls to the API for your own information, I would just manually retrieve your access token rather than worrying about automating it.
The user access token generated by LinkedIn when you authorize a given application is permanent unless you specify otherwise on the authorization screen. All you need to do is to generate the authorization screen with your application, go through the process and upon success echo out and store your user access token (token and secret). Once you have that, you can hard code those into a file, database, etc and when making calls to the API, use those.
It's in PHP, but this demo does basically this. Just modify the demo.php script to echo out your token as needed.
I have not tried it myself, but I believe in theory it should be possible with Selenium WebDriver with PyVirtualDisplay. This idea is described here.
I'm having an issue correctly interfacing with a SOAP API running on Axis2:
What happens is I should call the login method with two arguments (loginName and password) and it returns an authentication token that I will use for subsequent interaction.
#!/usr/bin/python
from SOAPpy import SOAPProxy
s_user = 'Administrator'
s_pass = 'securityThroughObscurity'
s_host = '192.168.76.130:8998'
namespace = 'http://bcc.inc.com/IncSecurity'
url = 'http://' + s_host + '/axis2/services/IncSecurityService'
DHCPServ = SOAPProxy(url, namespace)
DHCPServ.config.dumpSOAPOut = 1
DHCPServ.config.dumpSOAPIn = 1
DHCPResp = DHCPServ.login(loginName=s_user, password=s_pass)
The Axis2 server on the other side returns an XML error stating Data element of the OM Node is NULL. Looking at the Axis2 logs, I see the error is adb_login.c(383) non nillable or minOuccrs != 0 element loginName missing
I then packet captured the login XML from a known working Java client versus the XML from this client and these are the differences between the two:
SOAPpy:
<ns1:login xmlns:ns1="http://bcc.inc.com/IncSecurity" SOAP-ENC:root="1">
<password xsi:type="xsd:string">securityThroughObscurity</password>
<loginName xsi:type="xsd:string">Administrator</loginName>
</ns1:login>
Java:
<ns2:login xmlns:ns2="http://bcc.inc.com/IncSecurity">
<ns2:loginName>Administrator</ns2:loginName>
<ns2:password>securityThroughObscurity</ns2:password>
</ns2:login>
So this means that for some reason (probably related to my lack of knowledge in Python and SOAPpy) the namespace is not being applied to the variables being used in the login method, so by all accounts they don't actually exist and the error is warranted.
Also, it seems to be flipping the variables around and putting the password before loginName but I don't think that matters much.
What am I doing wrong?
Looks like it's a known bug in SOAPPy, someone has suggested a simple patch: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=523083
Alternately (assuming you have access to the service WSDL), SOAPPy lets you specify a WSDL instead of just a namespace. This looks like it will provide better namespace information to the envelope generation code. http://diveintopython.net/soap_web_services/introspection.html
Finally, if SOAPPy just isn't working for you, try Suds (it's better documented than SOAPPy).
from suds.client import Client
from suds.wsse import *
client = Client(WSDL_LOCATION)
guid = client.service.someFunctionName("a string argument", 42)
Good luck!
How can I check the number of unread Gmail message in my inbox with a short Python script? Bonus points for retrieving the password from a file.
import imaplib
obj = imaplib.IMAP4_SSL('imap.gmail.com','993')
obj.login('username','password')
obj.select()
obj.search(None,'UnSeen')
Well, I'm going to go ahead and spell out an imaplib solution as Cletus suggested. I don't see why people feel the need to use gmail.py or Atom for this. This kind of thing is what IMAP was designed for. Gmail.py is particularly egregious as it actually parses Gmail's HTML. That may be necessary for some things, but not to get a message count!
import imaplib, re
conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
conn.login(username, password)
unreadCount = re.search("UNSEEN (\d+)", conn.status("INBOX", "(UNSEEN)")[1][0]).group(1)
Pre-compiling the regex may improve performance slightly.
I advise you to use Gmail atom feed
It is as simple as this:
import urllib
url = 'https://mail.google.com/mail/feed/atom/'
opener = urllib.FancyURLopener()
f = opener.open(url)
feed = f.read()
You can then use the feed parse function in this nice article: Check Gmail the pythonic way
For a complete implementation of reading the value from the atom feed:
import urllib2
import base64
from xml.dom.minidom import parse
def gmail_unread_count(user, password):
"""
Takes a Gmail user name and password and returns the unread
messages count as an integer.
"""
# Build the authentication string
b64auth = base64.encodestring("%s:%s" % (user, password))
auth = "Basic " + b64auth
# Build the request
req = urllib2.Request("https://mail.google.com/mail/feed/atom/")
req.add_header("Authorization", auth)
handle = urllib2.urlopen(req)
# Build an XML dom tree of the feed
dom = parse(handle)
handle.close()
# Get the "fullcount" xml object
count_obj = dom.getElementsByTagName("fullcount")[0]
# get its text and convert it to an integer
return int(count_obj.firstChild.wholeText)
Well it isn't a code snippet but I imagine using imaplib and the Gmail IMAP instructions get you most of the way there.
Once you are logged in (do this manually or with gmail.py) you should use the feed.
It is located here:
http://mail.google.com/mail/feed/atom
It is the way Google does it. Here is a link to their js chrome extension:
http://dev.chromium.org/developers/design-documents/extensions/samples/gmail.zip
You will then be able to parse xml that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<title>Gmail - Inbox for yourmail#gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>142</fullcount>
I didn't like the existing solutions so I decided to make a sister library for my email sender called Red Box.
It has a pre-configured gmail instance:
from redbox import gmail
# Configure Gmail
gmail.username = "example#gmail.com"
gmail.password = "<PASSWORD>"
# Select inbox folder
inbox = gmail.inbox
# Get unread emails
msgs_unread = inbox.search(seen=False)
# Print unread count
print(len(msgs_unread))
Red Box fetches the email contents only when needed. The above does not do that as we didn't access the contents of these messages. You can also easily access various parts of the messages if you need.
I also wrote how to configure Gmail's app password here:
To install:
pip install redbox
Links:
Source code
Documentation
Use Gmail.py
file = open("filename","r")
usr = file.readline()
pwd = file.readline()
gmail = GmailClient()
gmail.login(usr, pwd)
unreadMail = gmail.get_inbox_conversations(is_unread=True)
print unreadMail
Gets login information from a text file assuming the login name and password are on separate lines.