def test_create_converts_key_to_unicode(self): """ The user_account_key attr should be unicode even if a bytestring was provided. """ user_api_from_unicode = VumiUserApi(self.vumi_api, u'foo') self.assertIsInstance(user_api_from_unicode.user_account_key, unicode) user_api_from_bytes = VumiUserApi(self.vumi_api, 'foo') self.assertIsInstance(user_api_from_bytes.user_account_key, unicode)
def export_contacts(account_key, contact_keys, include_extra=True): """ Export a list of contacts as a CSV file and email to the account holders' email address. :param str account_key: The account holders account key :param str contact_keys: The keys of the contacts to export :param bool include_extra: Whether or not to include the extra data stored in the dynamic field. """ api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store contacts = contacts_by_key(contact_store, *contact_keys) data = contacts_to_csv(contacts, include_extra) file = zipped_file('contacts-export.csv', data) # Get the profile for this user so we can email them when the import # has been completed. user_profile = UserProfile.objects.get(user_account=account_key) email = EmailMessage( 'Contacts export', 'Please find the CSV data for %s contact(s)' % len(contacts), settings.DEFAULT_FROM_EMAIL, [user_profile.user.email]) email.attach('contacts-export.zip', file, 'application/zip') email.send()
def export_many_group_contacts(account_key, group_keys, include_extra=True): """ Export multiple group contacts as a single CSV file and email to the account holders' email address. :param str account_key: The account holders account key :param list group_keys: The groups to export contacts for (can be either static or smart groups) :param bool include_extra: Whether or not to include the extra data stored in the dynamic field. """ api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store groups = [contact_store.get_group(k) for k in group_keys] contacts = get_group_contacts(contact_store, *groups) data = contacts_to_csv(contacts, include_extra) file = zipped_file('contacts-export.csv', data) # Get the profile for this user so we can email them when the import # has been completed. user_profile = UserProfile.objects.get(user_account=account_key) email = EmailMessage( 'Contacts export', 'Please find the attached CSV data for %s contact(s) from the ' 'following groups:\n%s\n' % (len(contacts), '\n'.join(' - %s' % g.name for g in groups)), settings.DEFAULT_FROM_EMAIL, [user_profile.user.email]) email.attach('contacts-export.zip', file, 'application/zip') email.send()
def export_group_contacts(account_key, group_key, include_extra=True): """ Export a group's contacts as a CSV file and email to the account holders' email address. :param str account_key: The account holders account key :param str group_key: The group to export contacts for (can be either static or smart groups) :param bool include_extra: Whether or not to include the extra data stored in the dynamic field. """ api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store group = contact_store.get_group(group_key) contacts = get_group_contacts(contact_store, group) data = contacts_to_csv(contacts, include_extra) file = zipped_file('contacts-export.csv', data) # Get the profile for this user so we can email them when the import # has been completed. user_profile = UserProfile.objects.get(user_account=account_key) email = EmailMessage( '%s contacts export' % (group.name, ), 'Please find the CSV data for %s contact(s) from ' 'group "%s" attached.\n\n' % (len(contacts), group.name), settings.DEFAULT_FROM_EMAIL, [user_profile.user.email]) email.attach('contacts-export.zip', file, 'application/zip') email.send()
def export_group_contacts(account_key, group_key, include_extra=True): """ Export a group's contacts as a CSV file and email to the account holders' email address. :param str account_key: The account holders account key :param str group_key: The group to export contacts for (can be either static or smart groups) :param bool include_extra: Whether or not to include the extra data stored in the dynamic field. """ api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store group = contact_store.get_group(group_key) contacts = get_group_contacts(contact_store, group) data = contacts_to_csv(contacts, include_extra) file = zipped_file('contacts-export.csv', data) # Get the profile for this user so we can email them when the import # has been completed. user_profile = UserProfile.objects.get(user_account=account_key) email = EmailMessage( '%s contacts export' % (group.name,), 'Please find the CSV data for %s contact(s) from ' 'group "%s" attached.\n\n' % (len(contacts), group.name), settings.DEFAULT_FROM_EMAIL, [user_profile.user.email]) email.attach('contacts-export.zip', file, 'application/zip') email.send()
def export_vxpolls_data(account_key, conversation_key, include_old_questions): """ Export the data from a vxpoll and send it as a zipped attachment via email. """ api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) user_profile = UserProfile.objects.get(user_account=account_key) conversation = api.get_wrapped_conversation(conversation_key) poll_id = 'poll-%s' % (conversation.key,) pm, poll_data = get_poll_config(poll_id) poll = pm.get(poll_id) csv_data = pm.export_user_data_as_csv( poll, include_old_questions=include_old_questions) email = EmailMessage( 'Survey export for: %s' % (conversation.name,), 'Please find the data for the survey %s attached.\n' % ( conversation.name), settings.DEFAULT_FROM_EMAIL, [user_profile.user.email]) zipio = StringIO() zf = ZipFile(zipio, "a", ZIP_DEFLATED) zf.writestr("survey-data-export.csv", csv_data) zf.close() email.attach('survey-data-export.zip', zipio.getvalue(), 'application/zip') email.send()
def export_conversation_messages_unsorted(account_key, conversation_key): """ Export the messages from a conversation as they come from the message store. Completely unsorted. :param str account_key: The account holder's account account_key :param str conversation_key: The key of the conversation we want to export the messages for. """ user_api = VumiUserApi.from_config_sync( account_key, settings.VUMI_API_CONFIG) user_profile = UserProfile.objects.get(user_account=account_key) conversation = user_api.get_wrapped_conversation(conversation_key) io = StringIO() writer = UnicodeDictWriter(io, conversation_export_field_names) writer.writeheader() for messages in load_messages_in_chunks(conversation, 'inbound'): for message in messages: writer.writerow(row_for_inbound_message(message)) for messages in load_messages_in_chunks(conversation, 'outbound'): for message in messages: mdb = user_api.api.mdb writer.writerow(row_for_outbound_message(message, mdb)) email_export(user_profile, conversation, io)
def test_exists(self): self.assertTrue( (yield self.vumi_api.user_exists(self.user_helper.account_key))) self.assertTrue((yield self.user_api.exists())) self.assertFalse((yield self.vumi_api.user_exists('foo'))) self.assertFalse((yield VumiUserApi(self.vumi_api, 'foo').exists()))
def export_conversation_messages_unsorted(account_key, conversation_key): """ Export the messages from a conversation as they come from the message store. Completely unsorted. :param str account_key: The account holder's account account_key :param str conversation_key: The key of the conversation we want to export the messages for. """ user_api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) user_profile = UserProfile.objects.get(user_account=account_key) conversation = user_api.get_wrapped_conversation(conversation_key) io = StringIO() writer = UnicodeDictWriter(io, conversation_export_field_names) writer.writeheader() for messages in load_messages_in_chunks(conversation, 'inbound'): for message in messages: writer.writerow(row_for_inbound_message(message)) for messages in load_messages_in_chunks(conversation, 'outbound'): for message in messages: mdb = user_api.api.mdb writer.writerow(row_for_outbound_message(message, mdb)) email_export(user_profile, conversation, io)
def export_vxpolls_data(account_key, conversation_key, include_old_questions): """ Export the data from a vxpoll and send it as a zipped attachment via email. """ api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) user_profile = UserProfile.objects.get(user_account=account_key) conversation = api.get_wrapped_conversation(conversation_key) poll_id = "poll-%s" % (conversation.key,) pm, poll_data = get_poll_config(poll_id) poll = pm.get(poll_id) csv_data = pm.export_user_data_as_csv(poll, include_old_questions=include_old_questions) email = EmailMessage( "Survey export for: %s" % (conversation.name,), "Please find the data for the survey %s attached.\n" % (conversation.name), settings.DEFAULT_FROM_EMAIL, [user_profile.user.email], ) zipio = StringIO() zf = ZipFile(zipio, "a", ZIP_DEFLATED) zf.writestr("survey-data-export.csv", csv_data) zf.close() email.attach("survey-data-export.zip", zipio.getvalue(), "application/zip") email.send()
def delete_group_contacts(account_key, group_key): api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store group = contact_store.get_group(group_key) contacts = contact_store.get_contacts_for_group(group) # We do this one at a time because we're already saving them one at a time # and the boilerplate for fetching batches without having them all sit in # memory is ugly. for contact_key in contacts: contact_store.get_contact_by_key(contact_key).delete()
def export_all_contacts(account_key, include_extra=True): """ Export all contacts as a CSV file and email to the account holders' email address. :param str account_key: The account holders account key :param bool include_extra: Whether or not to include the extra data stored in the dynamic field. """ api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store contact_keys = contact_store.contacts.all_keys() return export_contacts(account_key, contact_keys, include_extra=include_extra)
def delete_group(account_key, group_key): # NOTE: There is a small chance that this can break when running in # production if the load is high and the queues have backed up. # What could happen is that while contacts are being removed from # the group, new contacts could have been added before the group # has been deleted. If this happens those contacts will have # secondary indexes in Riak pointing to a non-existent Group. api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store group = contact_store.get_group(group_key) # We do this one at a time because we're already saving them one at a time # and the boilerplate for fetching batches without having them all sit in # memory is ugly. for contact_key in group.backlinks.contacts(): contact = contact_store.get_contact_by_key(contact_key) contact.groups.remove(group) contact.save() group.delete()
def import_and_update_contacts(contact_mangler, account_key, group_key, file_name, file_path, fields, has_header): api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store group = contact_store.get_group(group_key) user_profile = UserProfile.objects.get(user_account=account_key) extension, parser = ContactFileParser.get_parser(file_name) contact_dictionaries = parser.parse_file(file_path, fields, has_header) errors = [] counter = 0 for contact_dictionary in contact_dictionaries: try: key = contact_dictionary.pop('key') contact = contact_store.get_contact_by_key(key) contact_dictionary = contact_mangler(contact, contact_dictionary) contact_store.update_contact(key, **contact_dictionary) counter += 1 except KeyError, e: errors.append((key, 'No key provided')) except ContactNotFoundError, e: errors.append((key, str(e)))
def import_new_contacts_file(account_key, group_key, file_name, file_path, fields, has_header): api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store group = contact_store.get_group(group_key) # Get the profile for this user so we can email them when the import # has been completed. user_profile = UserProfile.objects.get(user_account=account_key) written_contacts = [] try: extension, parser = ContactFileParser.get_parser(file_name) contact_dictionaries = parser.parse_file(file_path, fields, has_header) for counter, contact_dictionary in enumerate(contact_dictionaries): # Make sure we set this group they're being uploaded in to contact_dictionary['groups'] = [group.key] contact = contact_store.new_contact(**contact_dictionary) written_contacts.append(contact) send_mail('Contact import completed successfully.', render_to_string( 'contacts/import_completed_mail.txt', { 'count': counter, 'group': group, 'user': user_profile.user, }), settings.DEFAULT_FROM_EMAIL, [user_profile.user.email], fail_silently=False) except Exception: # Clean up if something went wrong, either everything is written # or nothing is written for contact in written_contacts: contact.delete() exc_type, exc_value, exc_traceback = sys.exc_info() send_mail('Something went wrong while importing the contacts.', render_to_string( 'contacts/import_failed_mail.txt', { 'user': user_profile.user, 'group_key': group_key, 'account_key': account_key, 'file_name': file_name, 'file_path': file_path, 'fields': fields, 'has_header': has_header, 'exception_type': exc_type, 'exception_value': mark_safe(exc_value), 'exception_traceback': mark_safe(traceback.format_tb(exc_traceback)), }), settings.DEFAULT_FROM_EMAIL, [ user_profile.user.email, '*****@*****.**', ], fail_silently=False) finally: default_storage.delete(file_path)
def import_new_contacts_file(account_key, group_key, file_name, file_path, fields, has_header): api = VumiUserApi.from_config_sync(account_key, settings.VUMI_API_CONFIG) contact_store = api.contact_store group = contact_store.get_group(group_key) # Get the profile for this user so we can email them when the import # has been completed. user_profile = UserProfile.objects.get(user_account=account_key) written_contacts = [] try: extension, parser = ContactFileParser.get_parser(file_name) contact_dictionaries = parser.parse_file(file_path, fields, has_header) for counter, contact_dictionary in enumerate(contact_dictionaries): # Make sure we set this group they're being uploaded in to contact_dictionary['groups'] = [group.key] contact = contact_store.new_contact(**contact_dictionary) written_contacts.append(contact) send_mail( 'Contact import completed successfully.', render_to_string('contacts/import_completed_mail.txt', { 'count': counter, 'group': group, 'user': user_profile.user, }), settings.DEFAULT_FROM_EMAIL, [user_profile.user.email], fail_silently=False) except Exception: # Clean up if something went wrong, either everything is written # or nothing is written for contact in written_contacts: contact.delete() exc_type, exc_value, exc_traceback = sys.exc_info() send_mail( 'Something went wrong while importing the contacts.', render_to_string('contacts/import_failed_mail.txt', { 'user': user_profile.user, 'group_key': group_key, 'account_key': account_key, 'file_name': file_name, 'file_path': file_path, 'fields': fields, 'has_header': has_header, 'exception_type': exc_type, 'exception_value': mark_safe(exc_value), 'exception_traceback': mark_safe( traceback.format_tb(exc_traceback)), }), settings.DEFAULT_FROM_EMAIL, [ user_profile.user.email, '*****@*****.**', ], fail_silently=False) finally: default_storage.delete(file_path)