{"id":84,"date":"2011-05-03T16:05:43","date_gmt":"2011-05-03T15:05:43","guid":{"rendered":"http:\/\/tempdetheux.food.blog\/2011\/05\/03\/zendesk-plugin-in-hipchat\/"},"modified":"2019-07-19T17:02:06","modified_gmt":"2019-07-19T15:02:06","slug":"zendesk-plugin-in-hipchat","status":"publish","type":"post","link":"https:\/\/arnaud.detheux.org\/blog\/zendesk-plugin-in-hipchat\/","title":{"rendered":"Zendesk plugin in HipChat"},"content":{"rendered":"<div id=\"bsf_rt_marker\"><\/div><p>I\u2019m finally active again on my blog!&nbsp;\ud83d\ude42<\/p>\n<p>For this first post I wanted to quickly show my little <a href=\"http:\/\/www.zendesk.com\" target=\"_blank\" rel=\"noopener noreferrer\">Zendesk<\/a> plugin for <a href=\"http:\/\/www.hipchat.com\" target=\"_blank\" rel=\"noopener noreferrer\">HipChat<\/a>. Our dev team created a bot in HipChat called R2D2 (yes, we have a lot of imagination!). We create different plugins for that bot (useful\u2026 or not) and call each plugin by typing&nbsp;!<em>plugin<\/em>.<\/p>\n<p>Note that the source of the bot itself is not available for now so you will need to hack my plugin to make it work in your HipChat account (or actually any other service, but HipChat rocks).<\/p>\n<p>I had the idea because, firstly I wanted to fool around with Python for the first time of my life<br \/>\nand the Zendesk API; secondly, because our CEO wanted a quick and easy way to have a view on our support team\u2019s performance. Instead of receiving a long reporting email each day or having to log into Zendesk to check the Reporting section, he can fire up the&nbsp;<em>!zendesk<\/em> command in HipChat and get the stats in a few seconds.<\/p>\n<p>I plan on adding other functionalities soon like SLAs statistics, average Time To Assign, average Time To Resolve, top performers,&nbsp;\u2026<\/p>\n<p>Demo<br \/>\n<em>Best viewed in fullscreen mode.<\/em><\/p>\n<p><a href=\"https:\/\/www.youtube.com\/embed\/_5Iq3fpWo14\">https:\/\/www.youtube.com\/embed\/_5Iq3fpWo14<\/a><\/p>\n<p>Source<\/p>\n<pre>#!\/usr\/bin\/env python<\/pre>\n<pre>__author__      = \"Arnaud de Theux\"\n__web__         = \"http:\/\/arnaud.detheux.org\"\n__twitter__     = \"@AdeTheux\"<\/pre>\n<pre>\"\"\"This is a python script that runs as a plugin on top of our HipChat chat bot. It displays information regarding your Zendesk account. To make it run, just complete the Settings part and your branded spokes URL. Note that some code needs our chat bot to run, you will need to modify the code for it to run without our bot\"\"\"<\/pre>\n<pre>import sys\nimport os\nimport httplib2\nfrom urllib import urlopen\nimport urllib\nfrom xml.dom.minidom import parseString\nimport re<\/pre>\n<pre>###Settings. Replace with your own Zendesk credentials and URL. If you don't use the API token (baaad) just put your password\nuser           = 'YOUR_USER_EMAIL_ADDRESS\/token'\npassword       = 'YOUR_TOKEN'\nzendesk        = 'http:\/\/ACCOUNT.zendesk.com\/' # the \/ at the end is important!<\/pre>\n<pre>###Fetches unsolved tickets view and returns only number of tickets\nclass ZendeskBot(BotPlugin):\n    @botcmd\n    def zendesk(self, mess, args):\n        self.send(mess.getFrom(), \"\/me is preparing the statistics... \", message_type=mess.getType())\n        h= httplib2.Http(\".cache\")\n        h.add_credentials(user, password)\n        resp, xml_view_opened = h.request(zendesk+\"rules\/YOUR_VIEW_ID.xml\", \"GET\", headers={'content-type' : 'application\/xml'} )\n        opened_tickets = re.search('    \n\n###Fetches satisfaction score of spoke\n        good = 0\n        bad  = 0\n        data = urlopen(\"http:\/\/SPOKE1.zendesk.com\/satisfaction.json\").readlines()[0]\n        good = data.count('1')\n        bad  = data.count('0')\n\n#Fetches satisfaction score of spoke\n        good1 = 0\n        bad1  = 0\n        data = urlopen(\"http:\/\/SPOKE2.zendesk.com\/satisfaction.json\").readlines()[0]\n        good1 = data.count('1')\n        bad1  = data.count('0')\n\n#Fetches satisfaction score of spoke\n        good2 = 0\n        bad2  = 0\n        data = urlopen(\"http:\/\/SPOKE3.zendesk.com\/satisfaction.json\").readlines()[0]\n        good2 = data.count('1')\n        bad2  = data.count('0')\n\n#Makes a sum of the satisfaction scores\n        sum_good = good + good1 + good2\n        sum_bad = bad + bad1 + bad2\n        sum_total = sum_good + sum_bad\n\n#Convert it to % in case there are not yet 100 ratings in Zendesk account\n        sum_good_percentage = round(float(sum_good)\/sum_total*100,0)\n        sum_bad_percentage = round(float(sum_bad)\/sum_bad*100,0)\n\n\n\n###Fetches the tags file\n        h= httplib2.Http(\".cache\")\n        h.add_credentials(user, password)\n        resp, content = h.request(zendesk+\"tags.xml\", \"GET\", headers={'content-type' : 'application\/xml'} )\n\n#Displays the top 10 tags (You need to replace [1] by [0] and increment accordingly below. I start from line 1 because I don't want the first tag to be displayed.\n#1\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[1].toxml()\n        xmlDataName=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[1].toxml()\n        xmlDataTag=xmlTag.replace('','').replace('','')\n#2\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[2].toxml()\n        xmlDataName1=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[2].toxml()\n        xmlDataTag1=xmlTag.replace('','').replace('','')\n#3\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[3].toxml()\n        xmlDataName2=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[3].toxml()\n        xmlDataTag2=xmlTag.replace('','').replace('','')\n#4\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[4].toxml()\n        xmlDataName3=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[4].toxml()\n        xmlDataTag3=xmlTag.replace('','').replace('','')\n#5\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[5].toxml()\n        xmlDataName4=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[5].toxml()\n        xmlDataTag4=xmlTag.replace('','').replace('','')\n#6\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[6].toxml()\n        xmlDataName5=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[6].toxml()\n        xmlDataTag5=xmlTag.replace('','').replace('','')\n#7\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[7].toxml()\n        xmlDataName6=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[7].toxml()\n        xmlDataTag6=xmlTag.replace('','').replace('','')\n#8\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[8].toxml()\n        xmlDataName7=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[8].toxml()\n        xmlDataTag7=xmlTag.replace('','').replace('','')\n#9\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[9].toxml()\n        xmlDataName8=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[9].toxml()\n        xmlDataTag8=xmlTag.replace('','').replace('','')\n#10\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('name')[10].toxml()\n        xmlDataName9=xmlTag.replace('','').replace('','')\n\n        dom = parseString(content)\n        xmlTag = dom.getElementsByTagName('count')[10].toxml()\n        xmlDataTag9=xmlTag.replace('','').replace('','')<\/pre>\n<pre>######### WORK IN PROGRESS #########\n###Fetches top performer\n#Displays the top performer by stripping of the  tags on latest tickets\n#        h= httplib2.Http(\".cache\")\n#        h.add_credentials(user, password)\n#        resp, xml_view_top_perf = h.request(zendesk+\"rules\/YOUR_VIEW_ID.xml\", \"GET\", headers={'content-type' : 'application\/xml'} )\n#\n#        dom = parseString(xml_view_top_perf)\n#        xmlTag = dom.getElementsByTagName('assignee-name')[0].toxml()\n#        xmlDataNameTopPerf=xmlTag.replace('','').replace('','')\n######### WORK IN PROGRESS #########<\/pre>\n<pre>###Display the ouput\n        if sum_good_percentage &gt;= 85:\n            result='There is a %i%% satisfaction rate. Good job!n' % sum_good_percentage\n        else:\n            result='There is a %i%% satisfaction rate. That's quite low, you should be ashamed!n' % sum_good_percentage\n\n        if opened_tickets &gt; 1:\n            result+='There is a total of %s unresolved requests at the moment. Chop chop, go solve them!n' % opened_tickets\n        else:\n            result+='There is a total of %s unresolved request at the moment. Chop chop, go solve it!n' % opened_tickets<\/pre>\n<pre>result+='These are the top 10 tags and their occurrences: '+xmlDataName+'('+xmlDataTag+') '+xmlDataName1+'('+xmlDataTag1+') '+xmlDataName2+'('+xmlDataTag2+') '+xmlDataName3+'('+xmlDataTag3+') '+xmlDataName4+'('+xmlDataTag4+') '+xmlDataName5+'('+xmlDataTag5+') '+xmlDataName6+'('+xmlDataTag6+') '+xmlDataName7+'('+xmlDataTag7+') '+xmlDataName8+'('+xmlDataTag8+') '+xmlDataName9+'('+xmlDataTag9+')n'\n\n#        result+='The top performer this week is %s. Give that man a raise!' % xmlDataNameTopPerf\n        return result<\/pre>\n<pre>You can find the source on my (empty :) ) <a href=\"https:\/\/github.com\/AdeTheux\/Zendesk-widgets\/blob\/master\/zendesk_hipchat_bot.py\" title=\"GitHub\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub account<\/a>.<\/pre>\n<pre>Enjoy!<\/pre>\n<pre>Update 12\/05\/2012\nHere is our VP of Engineering showing our bot's JIRA capabilities @ ABUG-3<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I\u2019m finally active again on my blog!&nbsp;\ud83d\ude42 For this first post I wanted to quickly show my little Zendesk plugin for HipChat. Our dev team created a bot in HipChat called R2D2 (yes, we have a lot of imagination!). We create different plugins for that bot (useful\u2026 or not) and call each plugin by typing&nbsp;!plugin.&hellip;<\/p>\n<p class=\"read-more\"><a class=\"readmore-btn\" href=\"https:\/\/arnaud.detheux.org\/blog\/zendesk-plugin-in-hipchat\/\">Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","jetpack_post_was_ever_published":false},"categories":[7],"tags":[63,20,34,49,50,57],"class_list":["post-84","post","type-post","status-publish","format-standard","hentry","category-customer-experience","tag-archive","tag-customer-support","tag-hipchat","tag-plugin","tag-r2d2","tag-zendesk"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/posts\/84","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/comments?post=84"}],"version-history":[{"count":2,"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/posts\/84\/revisions"}],"predecessor-version":[{"id":455,"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/posts\/84\/revisions\/455"}],"wp:attachment":[{"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/media?parent=84"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/categories?post=84"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/arnaud.detheux.org\/blog\/wp-json\/wp\/v2\/tags?post=84"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}