class ZenWorker(object): def __init__(self, url, email, api, search_string): self.zendesk = Zendesk(url, zdesk_email=email, zdesk_api=api) self.barcode_re = re.compile(r"barcode\s(\d+)") self.username_re = re.compile(r"assigned_to\s(\w+)") self.search = search_string self.me = self.zendesk.users_me()['user'] def run(self): """ Iterates through the tickets found by SEARCH_STRING and """ try: result = self.zendesk.search(query=self.search, get_all_pages=True) except Exception as exc: logging.error("encountered an exception during a zendesk search: %s", str(exc)) return logging.debug("found %s tickets in the queue", str(result['count'])) tickets = {} # iterating over the tickets which haven't been touched for ticket in result['results']: try: comments = self.zendesk.ticket_comments(ticket_id=ticket['id']) except Exception as exc: logging.error("encountered an error %s while trying to fetch comments " "for ticket: %s", str(exc), str(ticket['id'])) # check if it's open and there's a cmment from a human if ticket['status'] == 'open' and comments.get("count", 0) > 1: #and #comments['comments'][-1].get('author_id') != self.me['id']): logging.info("ticket %s is open and has comments", str(ticket['id'])) continue # get the user, barcode and ticket id user_match = self.username_re.search(ticket['description']) barcode_match = self.barcode_re.search(ticket['description']) if not (user_match and barcode_match): continue # TODO: uncomment user = user_match.group(1) barcode = barcode_match.group(1) tickets[ticket['id']] = TicketData(user, barcode, ticket['status']) return tickets def update_ticket(self, ticket_id, message): """ Updates a ticket with given ticket_id with a message. """ data = { "ticket": { "id": ticket_id, "comment": { "public": True, "body": message } } } response = self.zendesk.ticket_update(ticket_id, data) logging.debug(response)
def _deploy(article_id, zendesk_url, cloudfront_url, username, password): path = "site/" + article_id + "/index.html" locale = "en-us" # Check if the article_id is valid. if not os.path.exists("posts/" + article_id): print(Fore.RED + "The article_id you entered is invalid." + Fore.RESET) sys.exit(1) title = open("posts/" + article_id + "/title.html").readline() if not title: print(Fore.RED + "Add a title to posts/" + article_id + "/title.html before deploying the article." + Fore.RESET) sys.exit(1) # Prepare files for being pushed to Zendesk. renderer.render_zendesk_deployment(cloudfront_url, article_id) # Push the images to CloudFront. cloudfront_images.push_to_cloudfront(article_id) # Delete extra images on CloudFront. cloudfront_images.delete_from_cloudfront(article_id) # Build connection to Zendesk. zendesk = Zendesk(zendesk_url, username, password) if not compare_repos.compare_article_contents(article_id, zendesk): return # Packages the data in a dictionary matching the expected JSON. update_article = { "translation": { "title": title, "body": open(path, mode='rb').read() } } response = zendesk.help_center_article_translation_update( article_id, locale, update_article) # Check if article is in Draft mode. check_draft = response["translation"]["draft"] if check_draft: print(Fore.YELLOW + "Reminder that article " + article_id + " is still in draft mode." + Fore.RESET) print "Article " + article_id + " has been updated at: " + zendesk_url + "/" + article_id
def activate(self): if self.config is None: self.log.info("SocialSupport is not configured - plugin not " "activating.") else: # Configure clients auth = OAuthHandler(self.config['TWITTER_CONSUMER_KEY'], self.config['TWITTER_CONSUMER_SECRET']) auth.set_access_token(self.config['TWITTER_OAUTH_TOKEN'], self.config['TWITTER_OAUTH_SECRET']) self.twitter_client = API(auth) self.since_id = None self.zendesk_client = Zendesk(self.config['ZENDESK_INSTANCE_URI'], self.config['ZENDESK_USER'], self.config['ZENDESK_PASSWORD']) self.log.info("Starting SocialSupport.") super(SocialSupport, self).activate() # Set up persistence. self.log.info("Setting up persistence.") self['SUPPORT_TRAINING_CORPUS'] = [] self['SUPPORT_TRAINING_QUEUE'] = [] self['SUPPORT_TRAINER_QUEUE'] = {} self['TRAINER_SCOREBOARD'] = {}
def zd(request): try: # If a zdtestcfg exists, then prefer it because it has been # manually created just for test running. from zdtestcfg import testconfig config = testconfig except: try: import zdeskcfg # Create an object using the [zdesk] and [sandbox] sections of # ~/.zdeskcfg and the zdeskcfg module config = zdeskcfg.get_ini_config(section='sandbox') # It's possible that zdeskcfg is installed, but if the config # file does not exist or have a valid configuration, we should # not try to use it. if True not in map(bool, config.values()): config = {} except: config = {} if config: return Zendesk(**config) else: assert 0, 'No Zendesk configuration found.\n' \ 'Create tests/zdtestcfg.py or install and configure zdeskcfg.'
def __init__(self, **kwargs): self.DEBUG = kwargs.get('DEBUG', True) self.query_zendesk = kwargs.get('query_zendesk', False) # # Allow for override # self._tickets = kwargs.get('tickets', []) self.target_product_uuids = kwargs.get('product_uuids', []) self.matched_tickets = [] self.matched_products = [] self.matched_requesters = [] self.matched_users = [] zendesk = { 'zendesk_url': kwargs.get('zendesk_url', os.getenv('ZENDESK_URL')), 'username': kwargs.get('username', os.getenv('ZENDESK_USERNAME')), 'token': kwargs.get('token', os.getenv('ZENDESK_TOKEN')) } self.client = Zendesk(zendesk.get('zendesk_url'), zendesk.get('username'), zendesk.get('token')) logger.info('Initialized with kwargs: %s zendesk: %s' % (kwargs, zendesk))
def get_conn(self) -> Zendesk: conn = self.get_connection(self.__zendesk_conn_id) self.__url = "https://" + conn.host return Zendesk(zdesk_url=self.__url, zdesk_email=conn.login, zdesk_password=conn.password, zdesk_token=True)
def sync_remote(*args, **kwargs): zendesk = Zendesk( settings.ZENDESK_BASE_URL, settings.ZENDESK_EMAIL, settings.ZENDESK_PASSWORD, api_version=settings.ZENDESK_API_VERSION, ) field_names = Ticket.get_all_field_names("pk", "_fields") queryfmt = "type:ticket organization_id:{0.organization_external}" for company in Company.objects.all(): next_page = True page = 1 registers = [] while next_page: try: results = zendesk.search(query=queryfmt.format(company), page=page) except ZendeskError as err: # view does not exist if "error" in err.msg and err.error_code == 404: break if "results" not in results: break for ticket in results["results"]: params = {} for name in field_names: params[name] = ticket[name] obj = None try: obj = Ticket.objects.get(pk=params["id"]) for name, value in params.iteritems(): # update setattr(obj, name, value) except Ticket.DoesNotExist: obj = Ticket.objects.create(**params) finally: obj.fields = ticket["fields"] obj.save() registers.append(obj.pk) next_page = results.get("next_page", False) page += 1 # database clean Ticket.objects.filter(organization_id=company.organization_external).exclude(pk__in=registers).delete() return Ticket.objects.count()
class zendeskHandler(filterHandler): """ Handler that creates zendeks tickets. Currently hardcoding filter rules (eg uri) but could make this configurabe if desired. May also break these filterHandlers out into their own file that users could create independently of the subscription setup here.... """ def __init__(self, infopath='~/files/zendeskinfo.yaml'): import yaml from zdesk import Zendesk with open(os.path.expanduser(infopath), 'rt') as f: self.zendeskinfo = yaml.load(f) self.zendesk = Zendesk(**self.zendeskinfo) def filter(self, message): if message['options']['action'] != 'create': print('Annotation was not a creation, run update path?') return data = message['payload'][0] if 'scicrunch.org' in data['uri']: return True def handler(self, message): data = message['payload'][0] exact = [ i['exact'] for o in data['target'] for i in o['selector'] if 'selector' in o and 'exact' in i ] exact = exact[0] if exact else 'No description provided' href = data['links']['incontext'] new_ticket = { 'ticket': { 'requester': { 'name': 'hypothesis bot', 'email': self.zendeskinfo['zdesk_email'], }, 'subject': 'hypothes.is annotation on {} by {}'.format( data['document']['title'], data['user'].split(':', 1)[1]), 'description': '"{}" | {} {}'.format(exact, data['text'], href), 'tags': data['tags'], #'ticket_field_entries': [ #{ #'ticket_field_id':24394906, # referrer #'value': 'hypothes.is {}'.format(data['user'].split(':',1)[1]) # hypothes.is #}, #{ #'ticket_field_id':24394926, # url #'ticket_field_id':'Url', # url #'value': data['links']['incontext'] # incontext_url #} #] } } result = self.zendesk.ticket_create(data=new_ticket) print(result)
def _create_shell(section_id): # Get subdomain. try: subdomain = os.environ["ZENDESK_SUBDOMAIN"] url = file_constants.get_url_from_subdomain(subdomain) except KeyError: print(Fore.RED + "Please set the environment variable ZENDESK_SUBDOMAIN" + Fore.RESET) sys.exit(1) # Get username. try: username = os.environ["ZENDESK_USR"] except KeyError: print(Fore.RED + "Please set the environment variable ZENDESK_USR" + Fore.RESET) sys.exit(1) # Get password. try: password = os.environ["ZENDESK_PWD"] except KeyError: print(Fore.RED + "Please set the environment variable ZENDESK_PWD" + Fore.RESET) sys.exit(1) zendesk = Zendesk(url, username, password) # Add a temporary title and leave it in draft mode. new_article = {"article": {"title": "Temporary Title", "draft": True}} response = zendesk.help_center_section_article_create(id=section_id, data=new_article) # Report success. print('Successfully created the article.') # Create the article shell locally. article_id = response['article']['id'] _empty_article(str(article_id))
def zdeskNotify(self): room = "55a12b9bb82d04e3b232a99c" zendesk = Zendesk(**testconfig) results = zendesk.search(query='type:ticket sort:desc', page=1) for ticket in results['results']: if ticket['status'] == 'solved': #send message to ws #print "Hey man problem resolved" self.sayAnswer(room, "Андрей, мы нашли проблему и все исправили, пишите если опять будет регулярно повторяться проблема") ticket_id = ticket['id'] data = { "ticket": { "id": ticket_id, "status": "closed" } } response = zendesk.ticket_update(ticket_id, data) #self.sayAnswer(room, "ticket %s closed" % ticket_id) print "tiket %s closed" % ticket_id
def _deploy(article_id, zendesk_url, cloudfront_url, username, password): path = "site/" + article_id + "/index.html" locale = "en-us" # Check if the article_id is valid. if not os.path.exists("posts/" + article_id): print (Fore.RED + "The article_id you entered is invalid." + Fore.RESET) sys.exit(1) title = open("posts/" + article_id + "/title.html").readline() if not title: print (Fore.RED + "Add a title to posts/" + article_id + "/title.html before deploying the article." + Fore.RESET) sys.exit(1) # Prepare files for being pushed to Zendesk. renderer.render_zendesk_deployment(cloudfront_url, article_id) # Push the images to CloudFront. cloudfront_images.push_to_cloudfront(article_id) # Delete extra images on CloudFront. cloudfront_images.delete_from_cloudfront(article_id) # Build connection to Zendesk. zendesk = Zendesk(zendesk_url, username, password) if not compare_repos.compare_article_contents(article_id, zendesk): return # Packages the data in a dictionary matching the expected JSON. update_article = {"translation": {"title": title, "body": open(path, mode = 'rb').read()}} response = zendesk.help_center_article_translation_update(article_id, locale, update_article) # Check if article is in Draft mode. check_draft = response["translation"]["draft"] if check_draft: print (Fore.YELLOW + "Reminder that article " + article_id + " is still in draft mode." + Fore.RESET) print "Article " + article_id + " has been updated at: " + zendesk_url + "/" + article_id
def send_notification(self, subject, message, recipient=None): try: logger.info("Sending zendesk notification '%s'..." % subject) zendesk = Zendesk(self.auth_org_url, self.auth_email, self.auth_token, True) new_ticket = { 'ticket': { 'requester': { 'name': self.requester_name, 'email': self.requester_email, }, 'subject': subject, 'description': message, 'assignee_id': self.assignee_id } } zendesk.ticket_create(data=new_ticket) except Exception, e: logger.error("Error while sending zendesk notification:\n%s" % traceback.format_exc())
class zendeskHandler(filterHandler): """ Handler that creates zendeks tickets. Currently hardcoding filter rules (eg uri) but could make this configurabe if desired. May also break these filterHandlers out into their own file that users could create independently of the subscription setup here.... """ def __init__(self, infopath='~/files/zendeskinfo.yaml'): import yaml from zdesk import Zendesk with open(os.path.expanduser(infopath), 'rt') as f: self.zendeskinfo = yaml.load(f) self.zendesk = Zendesk(**self.zendeskinfo) def filter(self, message): if message['options']['action'] != 'create': print('Annotation was not a creation, run update path?') return data = message['payload'][0] if 'scicrunch.org' in data['uri']: return True def handler(self, message): data = message['payload'][0] exact = [i['exact'] for o in data['target'] for i in o['selector'] if 'selector' in o and 'exact' in i] exact = exact[0] if exact else 'No description provided' href = data['links']['incontext'] new_ticket = { 'ticket': { 'requester': { 'name': 'hypothesis bot', 'email': self.zendeskinfo['zdesk_email'], }, 'subject':'hypothes.is annotation on {} by {}'.format(data['document']['title'], data['user'].split(':',1)[1]), 'description': '"{}" | {} {}'.format(exact, data['text'], href) , 'tags': data['tags'], #'ticket_field_entries': [ #{ #'ticket_field_id':24394906, # referrer #'value': 'hypothes.is {}'.format(data['user'].split(':',1)[1]) # hypothes.is #}, #{ #'ticket_field_id':24394926, # url #'ticket_field_id':'Url', # url #'value': data['links']['incontext'] # incontext_url #} #] } } result = self.zendesk.ticket_create(data=new_ticket) print(result)
def _create_shell(section_id): # Get subdomain. try: subdomain = os.environ["ZENDESK_SUBDOMAIN"] url = file_constants.get_url_from_subdomain(subdomain) except KeyError: print(Fore.RED + "Please set the environment variable ZENDESK_SUBDOMAIN" + Fore.RESET) sys.exit(1) # Get username. try: username = os.environ["ZENDESK_USR"] except KeyError: print(Fore.RED + "Please set the environment variable ZENDESK_USR" + Fore.RESET) sys.exit(1) # Get password. try: password = os.environ["ZENDESK_PWD"] except KeyError: print(Fore.RED + "Please set the environment variable ZENDESK_PWD" + Fore.RESET) sys.exit(1) zendesk = Zendesk(url, username, password) # Add a temporary title and leave it in draft mode. new_article = {"article": {"title": "Temporary Title", "draft": True}} response = zendesk.help_center_section_article_create(id = section_id, data = new_article) # Report success. print('Successfully created the article.') # Create the article shell locally. article_id = response['article']['id'] _empty_article(str(article_id))
def zdgrab(verbose=False, tickets=None, work_dir=os.path.join(os.path.expanduser('~'), 'zdgrab'), agent='me', ss_host=None, ss_id=None, ss_secret=None, ss_command=None): "Download attachments from Zendesk tickets." # SendsafelyGrab will only be invoked if the comment body contains a link. # See the corresponding REGEX used by them, which has been ported to Python: # https://github.com/SendSafely/Windows-Client-API/blob/master/SendsafelyAPI/Utilities/ParseLinksUtility.cs ss_link_re = r'https://[-a-zA-Z\.]+/receive/\?[-A-Za-z0-9&=]+packageCode=[-A-Za-z0-9_]+#keyCode=[-A-Za-z0-9_]+' ss_link_pat = re.compile(ss_link_re) vp = verbose_printer(verbose) cfg = zdgrab.getconfig() if cfg['zdesk_url'] and ( cfg['zdesk_oauth'] or (cfg['zdesk_email'] and cfg['zdesk_password']) or (cfg['zdesk_email'] and cfg['zdesk_api']) ): vp.print('Configuring Zendesk with:\n' ' url: {}\n' ' email: {}\n' ' token: {}\n' ' password/oauth/api: (hidden)\n'.format(cfg['zdesk_url'], cfg['zdesk_email'], repr(cfg['zdesk_token']))) zd = Zendesk(**cfg) else: msg = textwrap.dedent("""\ Error: Need Zendesk config to continue. Config file (~/.zdeskcfg) should be something like: [zdesk] url = https://example.zendesk.com email = [email protected] api = dneib393fwEF3ifbsEXAMPLEdhb93dw343 # or # oauth = ndei393bEwF3ifbEsssX [zdgrab] agent = [email protected] """) print(msg) return 1 # Log the cfg vp.print('Running with zdgrab config:\n' ' verbose: {}\n' ' tickets: {}\n' ' work_dir: {}\n' ' agent: {}\n'.format(verbose, tickets, work_dir, agent)) # tickets=None means default to getting all of the attachments for this # user's open tickets. If tickets is given, try to split it into ints if tickets: # User gave a list of tickets try: tickets = [int(i) for i in tickets.split(',')] except ValueError: print('Error: Could not convert to integers: {}'.format(tickets)) return 1 # dict of paths to attachments retrieved to return. format is: # { 'path/to/ticket/1': [ 'path/to/attachment1', 'path/to/attachment2' ], # 'path/to/ticket/2': [ 'path/to/attachment1', 'path/to/attachment2' ] } grabs = {} # Save the current directory so we can go back once done start_dir = os.getcwd() # Normalize all of the given paths to absolute paths work_dir = os.path.abspath(work_dir) # Check for and create working directory if not os.path.isdir(work_dir): os.makedirs(work_dir) # Change to working directory to begin file output os.chdir(work_dir) vp.print('Retrieving tickets') if tickets: # tickets given, query for those response = zd.tickets_show_many(ids=','.join([s for s in map(str, tickets)]), get_all_pages=True) result_field = 'tickets' else: # List of tickets not given. Get all of the attachments for all of this # user's open tickets. q = 'status<solved assignee:{}'.format(agent) response = zd.search(query=q, get_all_pages=True) result_field = 'results' if response['count'] == 0: # No tickets from which to get attachments print("No tickets provided for attachment retrieval.") return {} else: vp.print("Located {} tickets".format(response['count'])) results = response[result_field] # Fix up some headers to use for downloading the attachments. # We're going to borrow the zdesk object's httplib client. headers = {} if zd.zdesk_email is not None and zd.zdesk_password is not None: headers["Authorization"] = "Basic {}".format( base64.b64encode(zd.zdesk_email.encode('ascii') + b':' + zd.zdesk_password.encode('ascii'))) # Get the attachments from the given zendesk tickets for ticket in results: if result_field == 'results' and ticket['result_type'] != 'ticket': # This is not actually a ticket. Weird. Skip it. continue vp.print('Ticket {}'.format(ticket['id'])) ticket_dir = os.path.join(work_dir, str(ticket['id'])) ticket_com_dir = os.path.join(ticket_dir, 'comments') comment_num = 0 response = zd.ticket_audits(ticket_id=ticket['id'], get_all_pages=True) audits = response['audits'] for audit in audits: for event in audit['events']: if event['type'] != 'Comment': # This event isn't a comment. Skip it. continue comment_num += 1 comment_dir = os.path.join(ticket_com_dir, str(comment_num)) for attachment in event['attachments']: name = attachment['file_name'] if os.path.isfile(os.path.join(comment_dir, name)): vp.print(' Attachment {} already present'.format(name)) continue # Get this attachment vp.print(' Downloading attachment {}'.format(name)) # Check for and create the download directory if not os.path.isdir(comment_dir): os.makedirs(comment_dir) os.chdir(comment_dir) response = zd.client.request('GET', attachment['content_url'], headers=headers) if response.status_code != 200: print('Error downloading {}'.format( attachment['content_url'])) continue with open(name, 'wb') as f: f.write(response.content) # Check for and create the grabs entry to return if ticket_dir not in grabs: grabs[ticket_dir] = [] grabs[ticket_dir].append( os.path.join('comments', str(comment_num), name)) # Let's try to extract this if it's compressed zdsplode(name, verbose=verbose) if ss_command: if not ss_link_pat.search(event['body']): # Don't bother invoking SendSafelyGrab if the body has # no SendSafely links. continue try: ss_output = subprocess.check_output(ss_command.split() + ["-v", "-h", ss_host, "-k", ss_id, "-s", ss_secret, "-d", comment_dir, event['body']], stderr=sys.stderr) if ss_output: # Check for and create the grabs entry to return if ss_output and (ticket_dir not in grabs): grabs[ticket_dir] = [] for name in ss_output.splitlines(): namestr = name.decode() grabs[ticket_dir].append( os.path.join('comments', str(comment_num), namestr)) # Let's try to extract this if it's compressed os.chdir(comment_dir) zdsplode(namestr, verbose=verbose) except subprocess.CalledProcessError: # SendSafelyGrab.exe will print its own errors pass os.chdir(start_dir) return grabs
def __init__(self, infopath='~/files/zendeskinfo.yaml'): import yaml from zdesk import Zendesk with open(os.path.expanduser(infopath), 'rt') as f: self.zendeskinfo = yaml.load(f) self.zendesk = Zendesk(**self.zendeskinfo)
from zdesk import Zendesk from tokenizer import tokenize_text from sklearn.feature_extraction.text import TfidfVectorizer, HashingVectorizer import model from model import Ticket, User, session from datetime import datetime, date import os import sys from sklearn.externals import joblib from train import train import pickle import numpy as np from time import sleep zendesk = Zendesk("https://sent.zendesk.com", os.environ["EMAIL"], os.environ["PASSWORD"]) USERS = zendesk.users_list() ORGANIZATIONS = zendesk.organizations_list() print ORGANIZATIONS # load the saved vectorizer, classifier, and last time the database was checked for label reclassifications classifier = joblib.load('train/classifier.pickle') vectorizer = joblib.load('train/vectorizer.pickle') last_update = pickle.load(open('last_update_time.p', 'rb')) today = datetime.utcnow() sentiment_changed_tickets = Ticket.list_changed_tickets(today) def learn_new_data(): X_data = [] y_labels = []
def __init__(self, config): self.config = config self.zendesk = Zendesk(self.config['url'], self.config['user'], self.config['password'])
type=str, nargs='*', help='New word that will replace old word') parser.add_argument('--ask', help='Ask before applying the change', action='store_true') parser.add_argument('-d', '--dry-run', action='store_true') parser.add_argument('-v', '--verbose', action='store_true') args = parser.parse_args() if len(args.old) != len(args.new): print('OLD must have the same number of argument than NEW') sys.exit(1) zendesk = Zendesk(zdesk_url=args.url, zdesk_email=args.username, zdesk_password=args.token, zdesk_token=True) page = 1 articles = zendesk.help_center_articles_list(per_page=100, page=page) if args.ask and not query_yes_no('Found "' + str(articles['count']) + '". Do you want to keep going?'): sys.exit(1) while True: for article in articles['articles']: translations = zendesk.help_center_article_translations( article_id=article['id'], locales=args.locale) for translation in translations['translations']: for i in range(0, len(args.old)): if translation['body'] is None or args.old[
class ZenResolver(object): """ Class to query zendesk for tickets to update where we match a set of product uuids @TODO need to not jsut check subject and description but also ensure that the ticket is a valid "missing pdf" ticket @TODO need to ensure the email from teh request PDF includes the reply-to that is the users email address otherwise the zendesk auto reply wont work @USAGE: >>> s = ZenResolver(product_uuids=['6dce72d9-6375-41a6-90fc-f6ffdcd81fb6']) # get the tuple of those to be affected, (ticket_id, product_uuid, user_info) >>> print s.process() [(423, '6dce72d9-6375-41a6-90fc-f6ffdcd81fb6', {'name': u'JaneundKarsten', 'email': u'*****@*****.**'}), ...] # Mark the tickets in zendesk as solved >>> s.mark_resolved(matches=s.process()) 423 6dce72d9-6375-41a6-90fc-f6ffdcd81fb6 {'name': u'JaneundKarsten', 'email': u'*****@*****.**'} """ output_files = { 'tickets': os.path.abspath('tickets.json'), 'users': os.path.abspath('users.json'), } def __init__(self, **kwargs): self.DEBUG = kwargs.get('DEBUG', True) self.query_zendesk = kwargs.get('query_zendesk', False) # # Allow for override # self._tickets = kwargs.get('tickets', []) self.target_product_uuids = kwargs.get('product_uuids', []) self.matched_tickets = [] self.matched_products = [] self.matched_requesters = [] self.matched_users = [] zendesk = { 'zendesk_url': kwargs.get('zendesk_url', os.getenv('ZENDESK_URL')), 'username': kwargs.get('username', os.getenv('ZENDESK_USERNAME')), 'token': kwargs.get('token', os.getenv('ZENDESK_TOKEN')) } self.client = Zendesk(zendesk.get('zendesk_url'), zendesk.get('username'), zendesk.get('token')) logger.info('Initialized with kwargs: %s zendesk: %s' % (kwargs, zendesk)) @property def tickets(self): # # If there is an override # if self._tickets: return self._tickets filename = self.output_files.get('tickets') logger.debug('Reading tickets: %s' % filename) if os.path.exists(filename) is True and self.query_zendesk is False: resp = json.load(open(filename, 'r')) else: logger.debug('Querying zendesk for updated tickets: %s' % filename) resp = self.client.tickets_list(get_all_pages=True) with open(filename, 'w+') as fname: fname.write(json.dumps(resp)) return resp.get('tickets', []) @property def users(self): filename = self.output_files.get('users') logger.debug('Reading users: %s' % filename) if os.path.exists(filename) is True and self.query_zendesk is False: resp = json.load(open(filename, 'r')) else: resp = self.client.users_list(get_all_pages=True) with open(filename, 'w+') as fname: fname.write(json.dumps(resp)) return resp.get('users', []) def __match_tickets(self): """ Build a set of ticket_id requester_id and product_uuid to act apon may need to ensure that the tickets.json is up to date, by forcing query_zendesk=True """ for ticket in self.tickets: subject = ticket.get('subject') description = ticket.get('description') logger.debug('Trying to match for TicketId: %s and RequesterId: %s' % (ticket['id'], ticket.get('requester_id'))) #import pdb;pdb.set_trace() matched_product_uuid = [target for target in self.target_product_uuids if target in subject or target in description] logger.debug('Matched: %s' % matched_product_uuid) if matched_product_uuid: rid = ticket.get('requester_id') if not rid: # because sometimes there is no requestor logger.debug('RequesterId: %s was invalid' % ticket.get('requester_id')) else: logger.debug('Match found for TicketId: %s and RequesterId: %s' % (ticket['id'], ticket.get('requester_id'))) self.matched_tickets += [ticket['id']] self.matched_requesters += [ticket['requester_id']] self.matched_products += matched_product_uuid def __match_users(self): """ Find the matching user details from each request may need to ensure that the users.json is up to date, by forcing query_zendesk=True """ for user in self.users: user_id = user.get('id') indices = [i for i, x in enumerate(self.matched_requesters) if x == user_id] if indices: for i in indices: self.matched_requesters[i] = {'name':user['name'], 'email': user['email']} def mark_resolved(self, matches): """ Resolve the zendesk tickets from our tuple """ update_ticket_ids = [] for ticket_id, product_uuid, user_info in matches: update_ticket_ids += [ticket_id] self.resolve(tickets=update_ticket_ids) def resolve(self, tickets): """ Update the zendesk ticket_ids mark as solved and trigger the auto responses """ logger.info('Will be marking these tickets as resolved: %s' % tickets) update_ticket_data = {'tickets': [{'id': ticket_id, 'status': 'solved'} for ticket_id in tickets]} response = None if tickets and self.DEBUG is False: response = self.client.tickets_update_many(data=update_ticket_data) return response def process(self): """ Primary process call returns a tuple of tuples: (ticket_id, product_uuid, user_info) [(423, '6dce72d9-6375-41a6-90fc-f6ffdcd81fb6', {'name': u'JaneundKarsten', 'email': u'*****@*****.**'}), ...] """ self.__match_tickets() self.__match_users() return zip(self.matched_tickets, self.matched_products, self.matched_requesters)
def zdkb(verbose=False, listing=None, fetch=False, kb_dir=os.path.join(os.path.expanduser('~'), 'zdkb')): "Manage Zendesk knowledgbases" cfg = zdkb.getconfig() # Log the cfg if verbose: print('Running with zdkb config:\n' ' verbose: {}\n' ' listing: {}\n' ' kb_dir: {}\n'.format(verbose, listing, kb_dir)) #if state['categories'] or state['topics'] or state['forums'] or state['list_zdf']: if listing or fetch: if cfg['zdesk_url'] and cfg['zdesk_email'] and cfg['zdesk_password']: if verbose: print('Configuring Zendesk with:\n' ' url: {}\n' ' email: {}\n' ' token: {}\n' ' password: (hidden)\n'.format( cfg['zdesk_url'], cfg['zdesk_email'], repr(cfg['zdesk_token']))) zd = Zendesk(**cfg) else: msg = textwrap.dedent("""\ Config file (e.g. ~/.zdf2pdf.cfg) should be something like: [zdf2pdf] url = https://example.zendesk.com mail = [email protected] password = dneib393fwEF3ifbsEXAMPLEdhb93dw343 is_token = 1 """) print(msg) msg = textwrap.dedent("""\ Error: Need Zendesk config for requested operation. Config file (~/.zdeskcfg) should be something like: [zdesk] url = https://example.zendesk.com email = [email protected] password = dneib393fwEF3ifbsEXAMPLEdhb93dw343 token = 1 [zdkb] kb_dir = /path/to/kb_dir """) print(msg) return 1 # If any listing was requested we will do that and exit, regardless of # any other supplied options. if listing == 'all': # List available zendesk forums with their IDs and titles and exit. # Listing is formatted like for following: # 12345 Category 1 name # 09876 Forum 1 name # 54321 Forum 2 name # 67890 Category 2 name if verbose: print('Listing all forums') response = zd.forums_list(get_all_pages=True) forums = response['forums'] cat_ids = set(f['category_id'] for f in forums) categories = zd.categories_list(get_all_pages=True) for cat_id in cat_ids: if cat_id: try: cat_name = next(c['name'] for c in categories if c['id'] == cat_id) except StopIteration: cat_name = 'None' else: cat_id = 'None' cat_name = 'None' print('{} ({})'.format(cat_name, cat_id)) for forum in forums: if repr(forum['category_id']) == cat_id: print(' {} ({})'.format(forum['name'], forum['id'])) return 0 elif listing: if verbose: print('Listing all entries in forum {}'.format(listing)) # List a zendesk forum's entries with their titles and IDs and exit try: forum_id = int(listing) except ValueError: print('Error: Could not convert to integer: {}'.format(listing)) return 1 entries = zd.forum_topics(id=listing, get_all_pages=True) for entry in entries['topics']: print('{} ({})'.format(entry['title'], entry['id'])) return 0 # Save the current directory so we can go back once done start_dir = os.getcwd() # Normalize all of the given paths to absolute paths kb_dir = os.path.abspath(kb_dir) # Check for and create working directory if not os.path.isdir(kb_dir): print('kb_dir does not exist: {}'.format(kb_dir)) return 1 if fetch: # Change to working directory to begin file output os.chdir(kb_dir) response = zd.forums_list(get_all_pages=True) forums = response['forums'] response = zd.categories_list(get_all_pages=True) categories = response['categories'] response = zd.topics_list(get_all_pages=True) topics = response['topics'] with open('categories', 'w') as cat_file: json.dump(categories, cat_file) for forum in forums: forum_name = forum['name'].replace('/', '-') if not os.path.isdir(forum_name): os.mkdir(forum_name) os.chdir(forum_name) with open(forum_name + '.json', 'w') as forum_json: json.dump(forum, forum_json) os.chdir(kb_dir) for topic in topics: try: forum_name = next(f['name'] for f in forums if f['id'] == topic['forum_id']) except StopIteration: forum_name = 'None' forum_name = forum_name.replace('/', '-') if not os.path.isdir(forum_name): os.mkdir(forum_name) os.chdir(forum_name) topic_filename = topic['title'].replace('/', '-') with open(topic_filename + '.html', 'w') as topic_html: topic_html.write(topic['body']) with open(topic_filename + '.json', 'w') as topic_json: del topic['body'] json.dump(topic, topic_json) os.chdir(kb_dir) return 0 return 0
from zdesk import Zendesk app = Flask(__name__) app.config.from_pyfile('settings.py') celery = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL']) celery.conf.update(app.config) TaskBase = celery.Task class ContextTask(TaskBase): abstract = True def __call__(self, *args, **kwargs): with app.app_context(): return TaskBase.__call__(self, *args, **kwargs) celery.Task = ContextTask redis = StrictRedis(host=app.config['REDIS_HOST'], port=app.config['REDIS_PORT'], db=app.config['REDIS_DB']) zendesk = Zendesk(zdesk_url=app.config['ZENDESK_URL'], zdesk_email=app.config['ZENDESK_EMAIL'], zdesk_password=app.config['ZENDESK_TOKEN'], zdesk_token=True) from . import api # NOQA
{ "position": 2, "locale": "jp", "name": "テスト用", "description": "テスト用カテゴリ" } } zendesk.help_center_category_create(data=testCategoryData) sectionId = 360000342113 testSectionData = { "section": { "position": 2, "locale": "jp", "name": "テスト用セクション", "description": "テスト用セクション" }} zendesk.help_center_category_section_create(sectionId, testSectionData) if __name__ == '__main__': zendesk = Zendesk('https://yourcompany.zendesk.com', '*****@*****.**', 'passwd') articlesData = articlesDataFactory("sampleArticleData.xlsx") # taggerFieldData = taggerFieldDataFactory("sampleFieldData.xlsx") articlesCreateOnInstance(zendesk, articlesData) # taggerFieldCreate(zendesk, taggerFieldData)
#Define ZenDesk API Information config = { 'zdesk_email': '<ZENDESK_USER_EMAIL>', 'zdesk_password': '******', 'zdesk_url': '<ZENDESK_URL>', 'zdesk_token': <'TRUE OR FALSE'> } #Define telephone country code (if Active Directory numbers formatted without code) telephone_prefix = "1" #Connect to S3 with Boto3 s3 = boto3.client('s3') #Create ZenDesk Connection zendesk = Zendesk(**config) def lambda_handler(event, context): #List User users = zendesk.users_list().get('users', []) print("Listing Current ZenDesk Users") for user in users: name = user['name'] print(name) #Find Most Recently Modified Active Users File from S3 bucket_list = s3.list_objects(Bucket=bucket).get('Contents', []) print(bucket_list) for file in bucket_list:
def get_conn(self): conn = self.get_connection(self.__zendesk_conn_id) self.__url = "https://" + conn.host return Zendesk(self.__url, conn.login, conn.password, True)
class Command(BaseCommand): option_list = BaseCommand.option_list + ( make_option( '--to-csv', action='store_true', dest='to-csv', default=False, help='Export all relevant zendesk items to csv file'), ) def handle(self, *args, **options): self.load_settings() self.init_zen() if options["to-csv"]: self.to_csv() def load_settings(self): with open(os.path.expanduser("~/.hmcts-zendesk"), "r") as config_file: self.settings = yaml.load(config_file.read()) def init_csv(self, f, dialect=csv.excel): self.writer = csv.writer(f, dialect=dialect) def init_zen(self): self.zendesk = Zendesk( self.settings["url"], self.settings["email"], self.settings["password"]) def get_all_fieldnames(self): return \ SIMPLE_FIELDS + \ NEWLINE_FIELDS + \ STRUCTURED_FIELDS def to_csv(self): self.outfile = self.settings.get('outfile', 'zendump.csv') self.batch_size = 100 with open(self.outfile, "wb") as f: self.init_csv(f) self.writerow(self.get_all_fieldnames()) # CSV Header for ticket in self.yield_tickets(): self.writerow(self.ticket_to_row(ticket)) def writerow(self, row): self.writer.writerow([ cell.encode("utf-8") for cell in row]) def ticket_to_row(self, ticket): return \ self.get_simple_fields(ticket) + \ self.get_newline_fields(ticket) + \ self.get_structured_fields(ticket) def parse_simple_field(self, field): if field is None: return "" else: try: return field.encode("utf-8") except AttributeError: # ints return str(field).encode("utf-8") def get_simple_fields(self, ticket): return [ self.parse_simple_field(ticket.get(field)) for field in SIMPLE_FIELDS] def parse_newline_field(self, field): return field or "" def get_newline_fields(self, ticket): return [ self.parse_newline_field(ticket.get(field)) for field in NEWLINE_FIELDS] def parse_structured_field(self, field): if field is None: return "" else: try: return field.encode("utf-8") except AttributeError: # ints return str(field).encode("utf-8") def get_structured_fields(self, ticket): return [ self.parse_structured_field(ticket.get(field)) for field in STRUCTURED_FIELDS] def yield_tickets(self): """Generates batches of tickets""" for raw_query in self.settings["raw_queries"]: first_page = self.zendesk.search(raw_query=raw_query) for item in first_page["results"]: yield item count = first_page["count"] print "{} tickets from ZenDesk match filter.".format(count) page_count, remainder = divmod(count, self.batch_size) page_count = page_count + 1 if remainder else page_count for page_id in range(2, page_count): qpage = " page:{}".format(page_id) page = self.zendesk.search(raw_query=raw_query + qpage) for item in page["results"]: yield item
# # In either case, you can use your actual password and set `token = 0` or # `zdesk_token = False`, but it is a very good idea to configure an API token # by visiting this URL at your own Zendesk instance: # https://example.zendesk.com/settings/api/ try: import zdeskcfg # Create an object using the [zdesk] section of # ~/.zdeskcfg and the zdeskcfg module #zendesk = Zendesk(**zdeskcfg.get_ini_config()) # Create an object using the [zdesk] and [sandbox] sections of # ~/.zdeskcfg and the zdeskcfg module zendesk = Zendesk(**zdeskcfg.get_ini_config(section='sandbox')) except ImportError: testconfig = { 'zdesk_email': '*****@*****.**', 'zdesk_password': '******', 'zdesk_url': 'https://example-sandbox22012201.zendesk.com', 'zdesk_token': True } if testconfig[ 'zdesk_url'] == 'https://example-sandbox22012201.zendesk.com': print( 'Could not import zdeskcfg and no manual configuration provided.') print( 'Please `pip install zdeskcfg` or edit example with manual configuration.'
def __init__(self, url, email, api, search_string): self.zendesk = Zendesk(url, zdesk_email=email, zdesk_api=api) self.barcode_re = re.compile(r"barcode\s(\d+)") self.username_re = re.compile(r"assigned_to\s(\w+)") self.search = search_string self.me = self.zendesk.users_me()['user']
def zdkb(verbose=False, listing=None, fetch=False, kb_dir=os.path.join(os.path.expanduser('~'), 'zdkb')): "Manage Zendesk knowledgbases" cfg = zdkb.getconfig() # Log the cfg if verbose: print('Running with zdkb config:\n' ' verbose: {}\n' ' listing: {}\n' ' kb_dir: {}\n'.format(verbose, listing, kb_dir)) #if state['categories'] or state['topics'] or state['forums'] or state['list_zdf']: if listing or fetch: if cfg['zdesk_url'] and cfg['zdesk_email'] and cfg['zdesk_password']: if verbose: print('Configuring Zendesk with:\n' ' url: {}\n' ' email: {}\n' ' token: {}\n' ' password: (hidden)\n'.format( cfg['zdesk_url'], cfg['zdesk_email'], repr(cfg['zdesk_token']) )) zd = Zendesk(**cfg) else: msg = textwrap.dedent("""\ Config file (e.g. ~/.zdf2pdf.cfg) should be something like: [zdf2pdf] url = https://example.zendesk.com mail = [email protected] password = dneib393fwEF3ifbsEXAMPLEdhb93dw343 is_token = 1 """) print(msg) msg = textwrap.dedent("""\ Error: Need Zendesk config for requested operation. Config file (~/.zdeskcfg) should be something like: [zdesk] url = https://example.zendesk.com email = [email protected] password = dneib393fwEF3ifbsEXAMPLEdhb93dw343 token = 1 [zdkb] kb_dir = /path/to/kb_dir """) print(msg) return 1 # If any listing was requested we will do that and exit, regardless of # any other supplied options. if listing == 'all': # List available zendesk forums with their IDs and titles and exit. # Listing is formatted like for following: # 12345 Category 1 name # 09876 Forum 1 name # 54321 Forum 2 name # 67890 Category 2 name if verbose: print('Listing all forums') response = zd.forums_list(get_all_pages=True) forums = response['forums'] cat_ids = set(f['category_id'] for f in forums) categories = zd.categories_list(get_all_pages=True) for cat_id in cat_ids: if cat_id: try: cat_name = next(c['name'] for c in categories if c['id'] == cat_id) except StopIteration: cat_name = 'None' else: cat_id = 'None' cat_name = 'None' print('{} ({})'.format(cat_name, cat_id)) for forum in forums: if repr(forum['category_id']) == cat_id: print(' {} ({})'.format(forum['name'], forum['id'])) return 0 elif listing: if verbose: print('Listing all entries in forum {}'.format(listing)) # List a zendesk forum's entries with their titles and IDs and exit try: forum_id = int(listing) except ValueError: print('Error: Could not convert to integer: {}'.format(listing)) return 1 entries = zd.forum_topics(id=listing, get_all_pages=True) for entry in entries['topics']: print('{} ({})'.format(entry['title'], entry['id'])) return 0 # Save the current directory so we can go back once done start_dir = os.getcwd() # Normalize all of the given paths to absolute paths kb_dir = os.path.abspath(kb_dir) # Check for and create working directory if not os.path.isdir(kb_dir): print('kb_dir does not exist: {}'.format(kb_dir)) return 1 if fetch: # Change to working directory to begin file output os.chdir(kb_dir) response = zd.forums_list(get_all_pages=True) forums = response['forums'] response = zd.categories_list(get_all_pages=True) categories = response['categories'] response = zd.topics_list(get_all_pages=True) topics = response['topics'] with open('categories', 'w') as cat_file: json.dump(categories, cat_file) for forum in forums: forum_name = forum['name'].replace('/', '-') if not os.path.isdir(forum_name): os.mkdir(forum_name) os.chdir(forum_name) with open(forum_name + '.json', 'w') as forum_json: json.dump(forum, forum_json) os.chdir(kb_dir) for topic in topics: try: forum_name = next(f['name'] for f in forums if f['id'] == topic['forum_id']) except StopIteration: forum_name = 'None' forum_name = forum_name.replace('/', '-') if not os.path.isdir(forum_name): os.mkdir(forum_name) os.chdir(forum_name) topic_filename = topic['title'].replace('/', '-') with open(topic_filename + '.html', 'w') as topic_html: topic_html.write(topic['body']) with open(topic_filename + '.json', 'w') as topic_json: del topic['body'] json.dump(topic, topic_json) os.chdir(kb_dir) return 0 return 0
merch_dir = "C:\\Users\\DmitryDmytrenko\\Documents\\Technology\\DD\\Zendesk\\Py app\\Files From Brad Merch\\*.xlsx" wb = load_workbook(filename=max(glob.glob(merch_dir), key=os.path.getctime)) sheet = wb.worksheets[0] print(max(glob.glob(merch_dir), key=os.path.getctime)) print(sheet) reply = int(input("Please enter 1 to continue with the file and tab above ")) if reply == 1: print("Will process the file above to create ZD tickets!") else: print("Tickets won't be created") exit() zendesk = Zendesk(zdesk_url='https://envusa.zendesk.com', zdesk_email='*****@*****.**', zdesk_password='******', zdesk_token=True) needed_rows = list(sheet.rows)[1:] dictionary = {} for row in needed_rows: fcid = row[5].value order_id = row[0].value order_date = row[1].value name = row[2].value mail_code = row[3].value address = row[6].value.replace("\n", " ") requester_email = row[8].value requester_phone = row[7].value
def zdgrab(verbose=False, tickets=None, work_dir=os.path.join(os.path.expanduser('~'), 'zdgrab'), agent='me'): "Download attachments from Zendesk tickets." cfg = zdgrab.getconfig() if cfg['zdesk_url'] and cfg['zdesk_email'] and cfg['zdesk_password']: if verbose: print('Configuring Zendesk with:\n' ' url: {}\n' ' email: {}\n' ' token: {}\n' ' password: (hidden)\n'.format( cfg['zdesk_url'], cfg['zdesk_email'], repr(cfg['zdesk_token']) )) zd = Zendesk(**cfg) else: msg = textwrap.dedent("""\ Error: Need Zendesk config to continue. Config file (~/.zdeskcfg) should be something like: [zdesk] url = https://example.zendesk.com email = [email protected] password = dneib393fwEF3ifbsEXAMPLEdhb93dw343 token = 1 [zdgrab] agent = [email protected] """) print(msg) return 1 # Log the cfg if verbose: print('Running with zdgrab config:\n' ' verbose: {}\n' ' tickets: {}\n' ' work_dir: {}\n' ' agent: {}\n'.format(verbose, tickets, work_dir, agent)) # tickets=None means default to getting all of the attachments for this # user's open tickets. If tickets is given, try to split it into ints if tickets: # User gave a list of tickets try: tickets = [int(i) for i in tickets.split(',')] except ValueError: print('Error: Could not convert to integers: {}'.format(tickets)) return 1 # dict of paths to attachments retrieved to return. format is: # { 'path/to/ticket/1': [ 'path/to/attachment1', 'path/to/attachment2' ], # 'path/to/ticket/2': [ 'path/to/attachment1', 'path/to/attachment2' ] } grabs = {} # Save the current directory so we can go back once done start_dir = os.getcwd() # Normalize all of the given paths to absolute paths work_dir = os.path.abspath(work_dir) # Check for and create working directory if not os.path.isdir(work_dir): os.makedirs(work_dir) # Change to working directory to begin file output os.chdir(work_dir) if verbose: print('Retrieving tickets') if tickets: # tickets given, query for those response = zd.tickets_show_many(ids=','.join([s for s in map(str,tickets)]), get_all_pages=True) result_field = 'tickets' else: # List of tickets not given. Get all of the attachments for all of this # user's open tickets. q = 'status<solved assignee:{}'.format(agent) response = zd.search(query=q, get_all_pages=True) result_field = 'results' if response['count'] == 0: # No tickets from which to get attachments print("No tickets provided for attachment retrieval.") return {} results = response[result_field] # Fix up some headers to use for downloading the attachments. # We're going to borrow the zdesk object's httplib client. headers = {} if zd.zdesk_email is not None and zd.zdesk_password is not None: headers["Authorization"] = "Basic {}".format( base64.b64encode(zd.zdesk_email.encode('ascii') + b':' + zd.zdesk_password.encode('ascii'))) # Get the attachments from the given zendesk tickets for ticket in results: if result_field == 'results' and ticket['result_type'] != 'ticket': # This is not actually a ticket. Weird. Skip it. continue if verbose: print('Ticket {}'.format(ticket['id'])) ticket_dir = os.path.join(work_dir, str(ticket['id'])) ticket_com_dir = os.path.join(ticket_dir, 'comments') comment_num = 0 if verbose: print('Retrieving audits') response = zd.ticket_audits(ticket_id=ticket['id'], get_all_pages=True) audits = response['audits'] for audit in audits: for event in audit['events']: if event['type'] != 'Comment': # This event isn't a comment. Skip it. continue comment_num += 1 comment_dir = os.path.join(ticket_com_dir, str(comment_num)) if verbose and event['attachments']: print('Comment {}'.format(comment_num)) for attachment in event['attachments']: name = attachment['file_name'] if os.path.isfile(os.path.join(comment_dir, name)): if verbose: print('Attachment {} already present'.format(name)) continue # Get this attachment if verbose: print('Attachment {}'.format(name)) # Check for and create the download directory if not os.path.isdir(comment_dir): os.makedirs(comment_dir) os.chdir(comment_dir) response = zd.client.request('GET', attachment['content_url'], headers=headers) if response.status_code != 200: print('Error downloading {}'.format(attachment['content_url'])) continue with open(name, 'wb') as f: f.write(response.content) # Check for and create the grabs entry to return if ticket_dir not in grabs: grabs[ticket_dir] = [] grabs[ticket_dir].append( os.path.join('comments', str(comment_num), name) ) # Let's try to extract this if it's compressed zdsplode(name, verbose=verbose) os.chdir(start_dir) return grabs
# # In either case, you can use your actual password and set `token = 0` or # `zdesk_token = False`, but it is a very good idea to configure an API token # by visiting this URL at your own Zendesk instance: # https://example.zendesk.com/settings/api/ try: import zdeskcfg # Create an object using the [zdesk] section of # ~/.zdeskcfg and the zdeskcfg module # zendesk = Zendesk(**zdeskcfg.get_ini_config()) # Create an object using the [zdesk] and [sandbox] sections of # ~/.zdeskcfg and the zdeskcfg module zendesk = Zendesk(**zdeskcfg.get_ini_config(section='sandbox')) except ImportError: testconfig = { 'zdesk_email': '*****@*****.**', 'zdesk_password': '******', 'zdesk_url': 'https://example-sandbox22012201.zendesk.com', 'zdesk_token': True } if testconfig['zdesk_url'] == \ 'https://example-sandbox22012201.zendesk.com': print( 'Could not import zdeskcfg and no manual configuration provided.') print( 'Please `pip install zdeskcfg` or edit example with '
from zdesk import Zendesk import json from sys import argv import os zendesk = Zendesk('https://sent.zendesk.com', os.environ["EMAIL"], os.environ["PASSWORD"]) def main(jsonfile): precontent = open(jsonfile).read() content = json.loads(precontent) # jsonfile.close() for review in content["Reviews"]: new_ticket = { "ticket": { "requester": { "name": review["Author"].encode('ascii', 'ignore'), "email": "*****@*****.**" }, "subject": review["Title"].encode('ascii', 'ignore'), "comment": { "body": review["Content"].encode('ascii', 'ignore') } } } # Create the ticket and get its URL result = zendesk.ticket_create(data=new_ticket)
def z_search(query): # Connect to Zendesk API testconfig = { 'zdesk_email': '*****@*****.**', 'zdesk_password': '******', 'zdesk_url': 'https://mdsol.zendesk.com', 'zdesk_token': True } zendesk = Zendesk(**testconfig) # Initialize list results_list = [] # Direct query phrase search search_results = zendesk.help_center_articles_search(query=query) articles = search_results['results'] idx1 = 0 for article in articles: results_list.append(articles[idx1]) idx1 += 1 if len(results_list) >= 3: break print "Number of results after direct phrase search: " + str(len(results_list)) # Remove unnecessary words from query and re-search direct phrase if len(results_list) < 3: sw = stopwords.filterable parsed_query = filter(lambda w: not w in sw, query.split()) parsed_query_joined = ' '.join(parsed_query) search_results = zendesk.help_center_articles_search(query=parsed_query_joined) articles = search_results['results'] idx1 = 0 for article in articles: if articles[idx1] not in results_list: results_list.append(articles[idx1]) idx1 += 1 if len(results_list) >= 3: break print "Number of results after SW cleared direct phrase search: " + str(len(results_list)) # Search word-by-word for results from stopword-cleared phrase if len(results_list) < 3: for keyword in parsed_query: search_results = zendesk.help_center_articles_search(query=keyword) articles = search_results['results'] idx1 = 0 for article in articles: if articles[idx1] not in results_list: results_list.append(articles[idx1]) idx1 += 1 if len(results_list) >= 3: break print "Number of results after word-by-word search: " + str(len(results_list)) ###################################################################### # This section conducts a lemmatized version of the word-by-word # # search. Implementation TBD. # ###################################################################### # Lemmatize and search word-by-word from stopword-cleared phrase #if len(results_list) < 3: # # import nltk # from nltk.stem.wordnet import WordNetLemmatizer # # nltk.data.path.append('C:/Users/gabri/Desktop/techbot-dir') # lm = WordNetLemmatizer() # # for keyword in parsed_query: # lemmed_keyword = lm.lemmatize(keyword) # search_results = zendesk.help_center_articles_search(query=lemmed_keyword) # articles = search_results['results'] # # idx1 = 0 # for article in articles: # if articles[idx1] not in results_list: # results_list.append(articles[idx1]) # idx1 += 1 # if len(results_list) >= 3: # break # #print "Number of results after lemmatized word-by-word search: " + str(len(results_list)) return results_list
def init_zen(self): self.zendesk = Zendesk( self.settings["url"], self.settings["email"], self.settings["password"])