Beispiel #1
0
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)
Beispiel #2
0
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
Beispiel #3
0
    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'] = {}
Beispiel #4
0
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))
Beispiel #6
0
 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)
Beispiel #7
0
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()
Beispiel #8
0
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)
Beispiel #9
0
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))
Beispiel #10
0
	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())
Beispiel #13
0
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))
Beispiel #15
0
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
Beispiel #16
0
 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)
Beispiel #17
0
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 = []
Beispiel #18
0
 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)
Beispiel #21
0
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
Beispiel #22
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
Beispiel #23
0
            {
                "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)
Beispiel #24
0
#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:
Beispiel #25
0
 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
Beispiel #27
0
#
# 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.'
Beispiel #28
0
 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']
Beispiel #29
0
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
Beispiel #30
0
 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)
Beispiel #31
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
Beispiel #32
0
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
Beispiel #33
0
#
# 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 '
Beispiel #34
0
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)
Beispiel #35
0
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"])