chrishumphr1es Posted February 19, 2014 Share Posted February 19, 2014 My goal for my workflow is to run a bash command that uses ldapsearch to search my university's directory and return a list of contacts that operates similar to Alfred's contact search. I've got my bash script running fine, but I'm just unclear on how to format the returned information in the best way. Any guidance on script filtering and bash script returning would be great! I am relatively new at this, so excuse my poor terminology. Link to comment
Tyler Eich Posted February 19, 2014 Share Posted February 19, 2014 Have you read David Ferguson's post about script filter feedback? Link to comment
chrishumphr1es Posted February 19, 2014 Author Share Posted February 19, 2014 (edited) I have, I'm just not sure how to go about connecting the dots..I'm pretty green at all of this. Here's my output from the terminal (using generic parameters instead of specific for privacy) : command: ldapsearch -h ldap.server.com -x -b "dc=company,dc=com" "uid=*username*" "telephoneNumber" "mail" "uid" # extended LDIF # # LDAPv3 # base with scope subtree # filter: uid=*username* # requesting: telephoneNumber mail uid # # username, people, ex.com dn: uid=username, ou=people, dc=company, dc=com telephoneNumber: +1 111 111-1111 mail: email uid: username # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 I'd like to be able to return the telephonNumber, mail, and uid values back to alfred similar to the way it does for the built-in contacts. Is this possible? Even better would be to be able to trigger an email from the mail value. Edited February 19, 2014 by chrishumphr1es Link to comment
deanishe Posted February 19, 2014 Share Posted February 19, 2014 You have to parse the command output to extract the name, username, email etc. and then reformat each entry as XML that Alfred understands. If you're new to programming, I'd suggest you try something like Python, PHP or Ruby, which are a lot easier than bash. There are also great libraries that can help you generate results in the format Alfred needs. Regarding sending an email, make the email the arg value in the output and send it to another script that opens the URL mailto:{query}. {query} is how Alfred inserts the arg into your script. Link to comment
chrishumphr1es Posted February 21, 2014 Author Share Posted February 21, 2014 (edited) Thank you for your comments, they have been very helpful. I actually found a ldap python library online and a few helpful scripts which helped me write a python script that returns the info I need, my only confusion now is reformatting the xml file into the correct alfred format. Here's my script: #!/usr/local/bin/python import ldap, sys if __name__ == "__main__": ldap_server="ldap_server" username = "username" password= "password" # the following is the user_dn format provided by the ldap server user_dn = "uid="+username+",ou=people,dc=ex,dc=com" # adjust this to your base dn for searching base_dn = "dc=ex,dc=com" connect = ldap.open(ldap_server) search_filter = "uid="+username try: #if authentication successful, get the full user data connect.bind_s(user_dn,password) retrieveAttributes = ["mail", "telephoneNumber", "cn"] result = connect.search_s(base_dn,ldap.SCOPE_SUBTREE,search_filter,retrieveAttributes) # return all user data results connect.unbind_s() sys.stdout = open('/tmp/ldapres.xml', 'r+') print result except ldap.LDAPError: connect.unbind_s() print "authentication error" and here is my xml file: [('uid=username, ou=people, dc=ex, dc=com', {'telephoneNumber': ['+1 111 111 1111'], 'mail': ['email'], 'cn': ['full name']})] Any ideas on how to get this into the format alfred needs to display it correctly would be super helpful. I've replaced my specific login info and output with generics Thanks! Edited February 21, 2014 by chrishumphr1es Link to comment
deanishe Posted February 21, 2014 Share Posted February 21, 2014 See here for info on the file format Alfred requires. See here for how to generate XML with Python. To see a concrete example, look at the Workflow.send_feedback (line 501) and Item.elem (line 70) methods here. And change this, or it will not work (you need to write your XML output to sys.stdout). sys.stdout = open('/tmp/ldapres.xml', 'r+') print result If you want to write to a file, you do it like this: open('/path/to/file.xml', 'wb').write(text.encode('utf-8')) You shouldn't rebind sys.stdout, and if you do, be sure to change it right back again. Link to comment
chrishumphr1es Posted February 21, 2014 Author Share Posted February 21, 2014 Ok great, I think I've fixed it. My xmlfile looks like this: <?xml version="1.0"?> <items> <items><item arg="email" uid="username" valid="YES"><title title="name" /><subtitle subtitle="telephoneNumber :+1 111 111 1111 mail : mail" /></item></items> </items> Will this work for the script filter? How do I tell the script filter to call the file? I've been reading all of the docs in the forums, and am still a bit stuck. Link to comment
deanishe Posted February 21, 2014 Share Posted February 21, 2014 (edited) The XML should look like this: <?xml version="1.0"?> <items> <item arg="email@example.com" uid="username" valid="yes"> <title>name</title> <subtitle>telephoneNumber :+1 111 111 1111 mail : mail</subtitle> </item> <item arg="email2@example.com" uid="username2" valid="yes"> <title>another name</title> <subtitle>telephoneNumber :+1 111 111 1111 mail : mail</subtitle> </item> </items> You have double <items> tags and the contents of <title> and <subtitle> as attributes instead of text between the tags. If you post the code you're using to generate that output, I might be able to help a bit more. Edited February 21, 2014 by deanishe Link to comment
chrishumphr1es Posted February 21, 2014 Author Share Posted February 21, 2014 So how do I get alfred to show that? I think if you could help me with that part, I'd be all set. Link to comment
deanishe Posted February 21, 2014 Share Posted February 21, 2014 sys.stdout.write(your_xml_variable.encode('utf-8')) Link to comment
chrishumphr1es Posted February 21, 2014 Author Share Posted February 21, 2014 Ok, thanks so much. Does this go in my script filter? I know my responses are probably frustrating but I am new at this and just trying to figure it out. Please feel free to just not respond if you'd rather not, but you've been helpful so far and I really appreciate it. Would my script filter be as follows: sys.stdout.write('/tmp/ldapres.xml'.encode('utf-8')) ? Link to comment
deanishe Posted February 21, 2014 Share Posted February 21, 2014 No, that won't work. That will just send the filename to Alfred, not its contents. I'm afraid I don't understand exactly what you're doing. Did you just run your script to generate the list of people once and save the results? Or do you want it to run every time you search with Alfred? Assuming the former, and that /tmp/ldapres.xml is in the right format for Alfred, you would instead use bash (not Python) and your script filter would be: cat /tmp/ldapres.xml However, this won't allow you to search the contacts in Alfred. To do that, your script filter needs to accept Alfred's {query} and use that to filter its list of contacts. Link to comment
Tyler Eich Posted February 21, 2014 Share Posted February 21, 2014 (edited) Ok, thanks so much. Does this go in my script filter? I know my responses are probably frustrating but I am new at this and just trying to figure it out. Please feel free to just not respond if you'd rather not, but you've been helpful so far and I really appreciate it. Would my script filter be as follows: sys.stdout.write('/tmp/ldapres.xml'.encode('utf-8')) ? No, that would literally output "/tmp/ldapres.xml". Just off the top of my head, this should work (assuming /tmp/ldapres.xml is in the Alfred-friendly format @deanishe explained): sys.stdout.write( open('/tmp/ldapres.xml').read() ) If /tmp/ldapres.xml IS NOT in Alfred's XML format, you would need to load the XML, process into Alfred's format, and return that instead. For example (after you've processed it and saved your variable as an XML string to alfred_xml): sys.stdout.write( alfred_xml.encode('utf-8') ) Edited February 21, 2014 by Tyler Eich Link to comment
deanishe Posted February 21, 2014 Share Posted February 21, 2014 @Tyler: you don't want the .encode('utf-8') in that case as the XML file will (well, should) already be UTF-8. Link to comment
Tyler Eich Posted February 21, 2014 Share Posted February 21, 2014 @deanishe Thanks! Fixed. Link to comment
chrishumphr1es Posted February 21, 2014 Author Share Posted February 21, 2014 I think I've confused everyone pretty well for all of this, haha. Thank you guys for what you've done. I'm just going to post my workflow so I'll can show you what I've got. My workflow: https://www.dropbox.com/s/ujyop86u2ohercu/LDAPSearch.alfredworkflow - I've removed my login info and just have generic data in place. My hope is that i could 1. Search my company's ldap database 2. output the data I need into a file alfred can read 3. Be able to list the data similar to how alfred does with spotlighted contacts 4. be able to create a new email message from the listing. Any feedback you guys have would be great. Link to comment
deanishe Posted February 21, 2014 Share Posted February 21, 2014 (edited) Yeah, that's not really how script filters are supposed to work. I'm afraid I have to go to bed now (it's 1 a.m.), but I'll have a look over it in the morning and rejigger it a bit. How long does it take to run the script that caches the data from the LDAP server? Edited February 22, 2014 by deanishe Link to comment
chrishumphr1es Posted February 22, 2014 Author Share Posted February 22, 2014 It takes no time at all, at the most 10-30 seconds. Link to comment
chrishumphr1es Posted February 22, 2014 Author Share Posted February 22, 2014 Thanks so much Deanishe, I really appreciate your time on this. Link to comment
deanishe Posted February 22, 2014 Share Posted February 22, 2014 (edited) So, this should do more or less what you want. You'll have to edit the ldap_search.py file inside it to add your server address, username, password etc. near the top of the file before it will work. I've put loads of comments in the Script Filter and source file, so you should be able to see what's going on and alter it to your needs. Seeing as your server takes several seconds to respond, I created 2 separate actions. Run ldapupdate to download and cache a list of all your contacts on the LDAP server, then ldap [query] (where query is part of a name, email or phone number) to search the cached contacts. Edited February 22, 2014 by deanishe Link to comment
chrishumphr1es Posted February 24, 2014 Author Share Posted February 24, 2014 Thank you! Sorry I am just getting back. Do I move the py file to usr/local/bin/python? Link to comment
deanishe Posted February 24, 2014 Share Posted February 24, 2014 No, don't move it or you will break the workflow. You leave it exactly where it is (in the workflow), but you'll have to edit it to add your LDAP credentials. You do have python installed at /usr/local/bin/python, don't you? Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now