def create_ticket(self, user, ticket_fields): """Create a ticket in Zendesk.""" ticket = Ticket( subject=ticket_fields.get("subject"), comment={"body": ticket_fields.get("description")}, ticket_form_id=settings.ZENDESK_TICKET_FORM_ID, custom_fields=[ { "id": settings.ZENDESK_PRODUCT_FIELD_ID, "value": ticket_fields.get("product") }, { "id": settings.ZENDESK_CATEGORY_FIELD_ID, "value": ticket_fields.get("category") }, { "id": settings.ZENDESK_OS_FIELD_ID, "value": ticket_fields.get("os") }, { "id": settings.ZENDESK_COUNTRY_FIELD_ID, "value": ticket_fields.get("country") }, ], ) if user.profile.zendesk_id: # TODO: is this necessary if we're updating users as soon as they're updated locally? ticket.requester_id = self.update_user(user).id else: ticket.requester_id = self.create_user(user).id return self.client.tickets.create(ticket)
def migrate_ticket(self, source, status_to_migrate='all'): end_time = 'N/A' try: end_time = source.generated_timestamp except AttributeError: pass if source.status == 'deleted': print('Skipping deleted ticket: %s (timestamp: %s)' % (source.id, end_time)) return 0 if (not status_to_migrate == 'all' and not status_to_migrate == 'not_closed' and not source.status == status_to_migrate) or \ (status_to_migrate == 'not_closed' and source.status == 'closed'): print('Skipping, ticket status is %s: %s (timestamp: %s)' % (source.status, source.id, end_time)) return 0 # Look for an existing ticket existing = self.find_target_ticket_for_original_id(source.id) if existing: # Existing tickets will be updated with the events API print('Existing ticket found for %s (timestamp: %s)' % (source.id, end_time)) return existing.id print('Migrating ticket %s - %s' % (source.id, source.subject)) ticket = Ticket(created_at=source.created_at, updated_at=source.updated_at, subject=source.subject, priority=source.priority, type=source.type, status=source.status, tags=source.tags, recipient=source.recipient, brand_id=self.get_target_brand_id(source.brand_id)) if source.ticket_form_id: ticket.ticket_form_id = self.get_target_ticket_form_id(source.ticket_form_id) # Organization org_id = source.organization_id if org_id: new_org_id = self.get_target_org_id(org_id) if new_org_id: ticket.organization_id = new_org_id # Collaborators collab_ids = source.collaborator_ids new_collab_ids = [] for collab_id in collab_ids: new_collab_ids.append(self.get_target_user_id(collab_id)) ticket.collaborator_ids = new_collab_ids # Custom fields source_fields = source.custom_fields custom_fields = {} for field in source_fields: custom_fields[self.get_target_ticket_field_id(field.get('id'))] = field.get('value') custom_fields[self.original_id_field] = source.id ticket.custom_fields = custom_fields # Comments comments = self.source_client.tickets.comments(source) new_comments = [] for comment in comments: new_comment = Comment(created_at=comment.created_at, html_body=comment.html_body, public=comment.public, metadata=comment.metadata) # Author author_id = comment.author_id new_comment.author_id = self.get_target_user_id(author_id) # Inline Attachments comment_body = comment.html_body uploads = [] matches = re.findall(self.HTML_IMG_TAG_PATTERN, comment_body) if len(matches) > 0: for match in matches: img_tag = match[0] url = match[1] print('- Found src url in comment: %s' % url) do_upload = False source_domain = '%s.zendesk.com' % self.SOURCE_INSTANCE source_alt_domain = '%s.zendesk.com' % self.SOURCE_ALT_INSTANCE if source_domain in url or source_alt_domain in url: do_upload = True url = url.replace(source_alt_domain, source_domain) elif self.SOURCE_HELPCENTER_DOMAIN in url: do_upload = True if do_upload: response = requests.get(url, auth=self.source_auth) if not response.status_code == 200: print('- ERROR getting attachment %s: %s' % (url, response.status_code)) continue file_name = 'attachment' content_disp = response.headers.get('content-disposition') if content_disp: file_name_match = re.search('inline; filename=\"(.*)\"', content_disp) if file_name_match: file_name = file_name_match.group(1) else: continue content_type = response.headers.get('content-type') if self.DEBUG: print('- DEBUG Attachment created - %s' % file_name) comment_body = comment_body.replace(img_tag, '<See Attachment>') else: with tempfile.TemporaryFile() as tmp_file: tmp_file.write(response.content) tmp_file.seek(0) try: upload = self.target_client.attachments.upload(fp=tmp_file, target_name=file_name, content_type=content_type) print('- Attachment created - %s' % file_name) comment_body = comment_body.replace(img_tag, '[See Attachment]') uploads.append(upload.token) except Exception as e: print('WARN Exception creating attachment %s - %s' % (file_name, e)) new_comment.html_body = comment_body # Non-inline Attachments attachments = comment.attachments if attachments and len(attachments) > 0: for attachment in attachments: url = attachment.content_url file_name = attachment.file_name content_type = attachment.content_type response = requests.get(url) if self.DEBUG: print('- DEBUG Attachment created - %s' % file_name) else: with tempfile.TemporaryFile() as tmp_file: tmp_file.write(response.content) tmp_file.seek(0) try: upload = self.target_client.attachments.upload(fp=tmp_file, target_name=file_name, content_type=content_type) print('- Attachment created - %s' % file_name) uploads.append(upload.token) except Exception as e: print('WARN Exception creating attachment %s - %s' % (file_name, e)) new_comment.uploads = uploads new_comments.append(new_comment) ticket.comments = new_comments # Submitter ticket.submitter_id = self.get_target_user_id(source.submitter_id) # Requestor requester_id = source.requester_id if requester_id: requester = self.get_target_user(requester_id) if requester: if requester.suspended: # End-users can't be assigned tickets comment = Comment(body='Requester was %s (suspended)' % requester.name, public=False) ticket.comments.append(comment) else: ticket.requester_id = requester.id # Assignee assignee_id = source.assignee_id group_id = source.group_id if assignee_id: assignee = self.get_target_user(assignee_id) if assignee: if assignee.role == 'end-user': # End-users can't be assigned tickets comment = Comment(body='Assignee was %s (suspended)' % assignee.name, public=False) ticket.comments.append(comment) else: ticket.assignee_id = assignee.id elif group_id: ticket.group_id = self.get_target_group_id(group_id) # Linked source/problem_id source_problem_id = source.problem_id if source_problem_id: problem_ticket = self.find_target_ticket_for_original_id(source_problem_id) if problem_ticket: if problem_ticket.type == 'problem': print('- Linking existing problem ticket for %s' % source_problem_id) ticket.problem_id = problem_ticket.id else: # Can't link them comment = Comment(body='Linked ticket %s is not a problem, could not link' % problem_ticket.id, public=False) ticket.comments.append(comment) else: # Migrate the problem ticket if self.DEBUG: print('- DEBUG Problem ticket not found, creating for %s' % source_problem_id) else: print('- Problem ticket not found, creating for %s' % source_problem_id) source_problem = self.source_client.tickets(id=source_problem_id) ticket.problem_id = self.migrate_ticket(source_problem) # Wait 60 sec for this to show up time.sleep(60) new_ticket_id = None if self.DEBUG: print('- DEBUG Successfully migrated ticket %s to %s (timestamp: %s)' % (source.id, new_ticket_id, end_time)) else: new_ticket_id = self.target_client.ticket_import.create(ticket) print('- Successfully migrated ticket %s to %s (timestamp: %s)' % (source.id, new_ticket_id, end_time)) return new_ticket_id