コード例 #1
0
    def create(self, request, *args, **kwargs):
        """
        Sends a websocket message to the user with the corresponding internal number
        """
        response = super(CallViewSet, self).create(request, *args, **kwargs)
        called_user = LilyUser.objects.filter(
            internal_number=request.data['internal_number'],
            tenant_id=request.user.tenant_id
        ).first()

        if not called_user:
            return response

        caller_number = parse_phone_number(request.data['caller_number'])
        account, contact = search_number(called_user.tenant_id, caller_number)

        # If a account with this number has been found, show information about and link to this account.
        if account:
            data = {
                'destination': 'account',
                'icon': static('app/images/notification_icons/account.png'),
                'params': {
                    'name': account.name,
                    'number': caller_number,
                    'id': account.id,
                },
            }

        # There is no account for the number, but if there is a contact, show information about and link to it.
        elif contact:
            data = {
                'destination': 'contact',
                'icon': static('app/images/notification_icons/contact.png'),
                'params': {
                    'name': contact.full_name,
                    'number': caller_number,
                    'id': contact.id,
                },
            }

        # If no account or contact has been found, use the name provided by VoIPGRID.
        else:
            data = {
                'destination': 'create',
                'icon': static('app/images/notification_icons/add-account.png'),
                'params': {
                    'name': request.data.get('caller_name'),
                    'number': caller_number,
                },
            }

        # Sends the data as a notification event to the user who picked up the phone.
        Group('user-%s' % called_user.id).send({
            'text': json.dumps({
                'event': 'notification',
                'data': data,
            }),
        })

        return response
コード例 #2
0
    def get(self, request, *args, **kwargs):
        number = kwargs.get('number', None)

        if number:
            # For now we'll always convert the phone number to a certain format.
            # In the future we might change how we handle phone numbers.
            number = parse_phone_number(number)

        response = {
            'data': {
                'accounts': [],
                'contacts': [],
            },
        }

        results = search_number(self.request.user.tenant_id, number)

        # Return only the primary keys of the accounts and contacts
        for account in results['data']['accounts']:
            response['data']['accounts'].append(account.id)

        for contact in results['data']['contacts']:
            response['data']['contacts'].append(contact.id)

        return HttpResponse(anyjson.dumps(response), content_type='application/json; charset=utf-8')
コード例 #3
0
ファイル: functions.py プロジェクト: kxion/hellolily
def search_number(tenant_id, number, return_related=True):
    """
    If the phone number belongs to an account, this returns the first account and all its contacts
    Else if the number belongs to a contact, this returns the first contact and all its accounts
    """
    phone_number = parse_phone_number(number)
    accounts = Account.objects.filter(phone_numbers__number=phone_number, is_deleted=False)
    contacts = Contact.objects.filter(phone_numbers__number=phone_number, is_deleted=False)

    accounts_result = []
    contacts_result = []

    if accounts:
        accounts_result = [accounts[0]]

        if return_related:
            contacts_result = accounts[0].contacts.filter(is_deleted=False)
    elif contacts:
        contacts_result = [contacts[0]]

        if return_related:
            accounts_result = contacts[0].accounts.filter(is_deleted=False)

    return {
        'data': {
            'accounts': accounts_result,
            'contacts': contacts_result,
        },
    }
コード例 #4
0
ファイル: models.py プロジェクト: rmoorman/hellolily
    def save(self, *args, **kwargs):
        # Save raw input as number only (for searching)
        self.number = parse_phone_number(self.raw_input)

        if len(self.number) > 0:
            # Overwrite user input
            self.raw_input = self.number  # reserved field for future display based on locale

        return super(PhoneNumber, self).save(*args, **kwargs)
コード例 #5
0
ファイル: views.py プロジェクト: HelloLily/hellolily
    def get(self, request, *args, **kwargs):
        number = kwargs.get("number", None)

        if number:
            # For now we'll always convert the phone number to a certain format.
            # In the future we might change how we handle phone numbers.
            number = parse_phone_number(number)

        results = self._search_number(number)

        return HttpResponse(anyjson.dumps(results), content_type="application/json; charset=utf-8")
コード例 #6
0
    def get(self, request, *args, **kwargs):
        number = kwargs.get('number', None)

        if number:
            # For now we'll always convert the phone number to a certain format.
            # In the future we might change how we handle phone numbers.
            number = parse_phone_number(number)

        results = self._search_number(number)

        return HttpResponse(anyjson.dumps(results),
                            content_type='application/json; charset=utf-8')
コード例 #7
0
    def _create_phone(self, instance, type, number, other_type=None):
        """
        Creates PhoneNumber for given instance

        Arguments:
            instance (instance): instance to add PhoneNumber to
            type (str): kind of phone number
            number (str): unformatted phone number
            other_type (str) optional: given if not default phone number type
        """
        if number and len(number) > 2:
            phone_kwargs = dict()
            phone_kwargs['type'] = type
            phone_kwargs['other_type'] = other_type
            phone_kwargs['number'] = parse_phone_number(number)
            phone_kwargs['tenant_id'] = self.tenant_pk

            phone_number_list = instance.phone_numbers.filter(**phone_kwargs)

            if not phone_number_list.exists():
                # Other types are ugly for phonenumbers.
                if other_type is not None:
                    phone_kwargs['type'] = phone_kwargs['other_type']
                    phone_kwargs['other_type'] = None

                # Recheck if it exists without the othertype.
                if not instance.phone_numbers.filter(**phone_kwargs).exists():
                    phone_number = PhoneNumber.objects.create(**phone_kwargs)
                    instance.phone_numbers.add(phone_number)
            else:

                # Keep first in list and delete all the others.
                for i, phone_number in enumerate(phone_number_list):
                    if i == 0:
                        # When othertype given set normal type instead for save.
                        if other_type is not None:
                            phone_number.type = phone_number.other_type
                            phone_kwargs['type'] = phone_number.other_type
                            phone_number.other_type = None
                            phone_kwargs['other_type'] = None
                            if not instance.phone_numbers.filter(
                                    **phone_kwargs).exists():
                                phone_number.save()
                    else:
                        phone_number.delete()
コード例 #8
0
ファイル: sugarcsvimport.py プロジェクト: noordzij/hellolily
    def _create_phone(self, instance, type, raw_input, other_type=None):
        """
        Creates PhoneNumber for given instance

        Arguments:
            instance (instance): instance to add PhoneNumber to
            type (str): kind of phone number
            raw_input (str): unformatted phone number
            other_type (str) optional: given if not default phone number type
        """
        if raw_input and len(raw_input) > 2:
            phone_kwargs = dict()
            phone_kwargs['type'] = type
            phone_kwargs['other_type'] = other_type
            phone_kwargs['raw_input'] = parse_phone_number(raw_input)
            phone_kwargs['tenant_id'] = self.tenant_pk

            phone_number_list = instance.phone_numbers.filter(**phone_kwargs)

            if not phone_number_list.exists():
                # Other types are ugly for phonenumbers.
                if other_type is not None:
                    phone_kwargs['type'] = phone_kwargs['other_type']
                    phone_kwargs['other_type'] = None

                # Recheck if it exists without the othertype.
                if not instance.phone_numbers.filter(**phone_kwargs).exists():
                    phone_number = PhoneNumber.objects.create(**phone_kwargs)
                    instance.phone_numbers.add(phone_number)
            else:

                # Keep first in list and delete all the others.
                for i, phone_number in enumerate(phone_number_list):
                    if i == 0:
                        # When othertype given set normal type instead for save.
                        if other_type is not None:
                            phone_number.type = phone_number.other_type
                            phone_kwargs['type'] = phone_number.other_type
                            phone_number.other_type = None
                            phone_kwargs['other_type'] = None
                            if not instance.phone_numbers.filter(**phone_kwargs).exists():
                                phone_number.save()
                    else:
                        phone_number.delete()
コード例 #9
0
    def get(self, request, *args, **kwargs):
        number = kwargs.get('number', None)

        if number:
            # For now we'll always convert the phone number to a certain format.
            # In the future we might change how we handle phone numbers.
            number = parse_phone_number(number)

        results = self._search_number(number)

        response_format = request.GET.get('format')

        if response_format and response_format.lower() == 'grid':
            name = ''
            internal_number = results.get('internal_number', '')

            result = search_number(request.user.tenant_id, number, False)
            data = result.get('data')
            accounts = data.get('accounts')
            contacts = data.get('contacts')

            if contacts:
                name = contacts[0].full_name
            elif accounts:
                name = accounts[0].name

            if name:
                response = 'status=ACK&callername=%s' % name

                if internal_number:
                    response += '&destination=%s' % internal_number
            else:
                response = 'status=NAK'

            return HttpResponse(response, content_type='text/plain; charset=utf-8')
        else:
            user = results.get('user')

            if user:
                results['user'] = user.id

        return HttpResponse(anyjson.dumps(results), content_type='application/json; charset=utf-8')
コード例 #10
0
def search_number(tenant_id, number):
    """
    Return the first account the number belongs to, otherwise if there is, return the first contact with that number.
    """
    contact = None
    phone_number = parse_phone_number(number)

    account = Account.objects.filter(phone_numbers__number=phone_number,
                                     tenant=tenant_id,
                                     is_deleted=False).only('id',
                                                            'name').first()

    if not account:
        contact = Contact.objects.filter(phone_numbers__number=phone_number,
                                         tenant=tenant_id,
                                         is_deleted=False).only(
                                             'id', 'first_name',
                                             'last_name').first()

    return account, contact
コード例 #11
0
ファイル: functions.py プロジェクト: HelloLily/hellolily
def search_number(tenant_id, number):
    """
    Return the first account the number belongs to, otherwise if there is, return the first contact with that number.
    """
    contact = None
    phone_number = parse_phone_number(number)

    account = Account.objects.filter(
        phone_numbers__number=phone_number,
        tenant=tenant_id,
        is_deleted=False
    ).only('id', 'name').first()

    if not account:
        contact = Contact.objects.filter(
            phone_numbers__number=phone_number,
            tenant=tenant_id,
            is_deleted=False
        ).only('id', 'first_name', 'last_name').first()

    return account, contact
コード例 #12
0
ファイル: views.py プロジェクト: HelloLily/hellolily
    def get(self, request, *args, **kwargs):
        phone_number = kwargs.get('number', None)

        if phone_number:
            # For now we'll always convert the phone number to a certain format.
            # In the future we might change how we handle phone numbers.
            phone_number = parse_phone_number(phone_number)

        results = self._get_user_internal_number(phone_number)

        response_format = request.GET.get('format')
        if response_format and response_format.lower() == 'grid':
            name = None
            internal_number = results.get('internal_number', '')

            account, contact = search_number(request.user.tenant_id, phone_number)

            if contact:
                name = contact.full_name
            elif account:
                name = account.name

            if name:
                response = 'status=ACK&callername=%s' % name

                if internal_number:
                    response += '&destination=%s' % internal_number
            else:
                response = 'status=NAK'

            return HttpResponse(response, content_type='text/plain; charset=utf-8')
        else:
            user = results.get('user')

            if user:
                results['user'] = user.id

        return HttpResponse(anyjson.dumps(results), content_type='application/json; charset=utf-8')
コード例 #13
0
def import_contact(row, tenant_id, headers):
    # The following set of fields should be present as headers in the uploaded file.
    required_fields = {u'first name', u'last name'}
    # The following set of fields are optional.
    optional_fields = {u'company name', u'email address', u'phone number', u'address', u'postal code', u'city',
                       u'twitter', u'linkedin', u'mobile'}

    # The following headers are present in the uploaded file.
    available_in_upload = set(headers)

    optional_in_upload = optional_fields & available_in_upload
    extra_in_upload = available_in_upload - (required_fields | optional_fields)

    first_name = row.get(u'first name')
    last_name = row.get(u'last name')
    full_name = u'{0} {1}'.format(first_name, last_name)

    contact = new_or_existing_contact(row, tenant_id, optional_in_upload)

    account = None
    email_address = None
    phone_number = None
    address = None
    twitter = None
    linkedin = None
    mobile = None
    try:
        # Use atomic to rollback all intermediate database actions if an error occurs in just one of them.
        with transaction.atomic():
            # All the extra fields excluding 'company' that are present in the upload are placed in the description
            # field.
            description = u''
            extra_in_upload_wo_company = set(extra_in_upload)
            extra_in_upload_wo_company.discard(u'company name')
            for field in extra_in_upload_wo_company:
                if row.get(field):
                    description += '{0}: {1}\n'.format(field.capitalize(), row.get(field))

            contact.description = description
            contact.save()

            if u'company name' in optional_in_upload and row.get(u'company name'):
                company_name = row.get(u'company name')
                # Not using get_or_create() to make use of the skip_signal construction.
                try:
                    account = Account.objects.get(name=company_name, tenant_id=tenant_id, is_deleted=False)
                except Account.DoesNotExist:
                    account_status = AccountStatus.objects.get(name='Relation', tenant_id=tenant_id)
                    account = Account(
                        name=company_name,
                        tenant_id=tenant_id,
                        status=account_status
                    )
                    account.skip_signal = True
                    account.save()

            if u'email address' in optional_in_upload and row.get(u'email address'):
                formatted_email_address = row.get(u'email address').lower()
                if not contact.email_addresses.filter(email_address=formatted_email_address).exists():
                    email_address = EmailAddress(
                        email_address=formatted_email_address,
                        status=EmailAddress.PRIMARY_STATUS,
                        tenant_id=tenant_id
                    )
                    email_address.skip_signal = True
                    email_address.save()

            if u'phone number' in optional_in_upload and row.get(u'phone number'):
                formatted_phone_number = parse_phone_number(row.get(u'phone number'))
                if not contact.phone_numbers.filter(number=formatted_phone_number).exists():
                    phone_number = PhoneNumber(
                        number=formatted_phone_number,
                        tenant_id=tenant_id
                    )
                    phone_number.skip_signal = True
                    phone_number.save()

            # An Address consists of multiple, optional fields. So create or update the instance.
            if u'address' in optional_in_upload and row.get(u'address'):
                address = Address(
                    address=row.get(u'address'),
                    type='visiting',
                    tenant_id=tenant_id
                )
                address.skip_signal = True
                address.save()

            if u'postal code' in optional_in_upload and row.get(u'postal code'):
                if address:
                    address.postal_code = row.get(u'postal code')
                else:
                    address = Address(
                        postal_code=row.get(u'postal code'),
                        type='visiting',
                        tenant_id=tenant_id
                    )
                address.skip_signal = True
                address.save()

            if u'city' in optional_in_upload and row.get(u'city'):
                if address:
                    address.city = row.get(u'city')
                else:
                    address = Address(
                        city=row.get(u'city'),
                        type='visiting',
                        tenant_id=tenant_id
                    )
                address.skip_signal = True
                address.save()

            if u'twitter' in optional_in_upload and row.get(u'twitter'):
                twitter = SocialMedia(
                    name='twitter',
                    username=row.get(u'twitter'),
                    profile_url='https://twitter.com/{0}'.format(row.get(u'twitter')),
                    tenant_id=tenant_id
                )
                twitter.skip_signal = True
                twitter.save()

            if u'linkedin' in optional_in_upload and row.get(u'linkedin'):
                linkedin = SocialMedia(
                    name='linkedin',
                    username=row.get(u'linkedin'),
                    profile_url='https://www.linkedin.com/in/{0}'.format(row.get(u'linkedin')),
                    tenant_id=tenant_id
                )
                linkedin.skip_signal = True
                linkedin.save()

            if u'mobile' in optional_in_upload and row.get(u'mobile'):
                formatted_phone_number = parse_phone_number(row.get(u'mobile'))
                if not contact.phone_numbers.filter(number=formatted_phone_number).exists():
                    mobile = PhoneNumber(
                        number=formatted_phone_number,
                        tenant_id=tenant_id,
                        type='mobile'
                    )
                    mobile.skip_signal = True
                    mobile.save()

    except Exception as e:
        # On an exception all database actions are rolled back. Because of the skip_signal=True no row is added to the
        # search index.
        logger.error(u'Import error for {}: {}'.format(full_name, e))
    else:
        if email_address:
            email_address.skip_signal = False
            email_address.save()
            contact.email_addresses.add(email_address)
        if phone_number:
            phone_number.skip_signal = False
            phone_number.save()
            contact.phone_numbers.add(phone_number)
        if address:
            address.skip_signal = False
            address.save()
            contact.addresses.add(address)
        if twitter:
            twitter.skip_signal = False
            twitter.save()
            contact.social_media.add(twitter)
        if linkedin:
            linkedin.skip_signal = False
            linkedin.save()
            contact.social_media.add(linkedin)
        if account:
            account.skip_signal = False
            account.save()

            if not Function.objects.filter(account=account, contact=contact).exists():
                Function.objects.create(account=account, contact=contact)
        if mobile:
            mobile.skip_signal = False
            mobile.save()
            contact.phone_numbers.add(mobile)

        contact.skip_signal = False
        contact.save()
コード例 #14
0
def import_account(row, tenant_id, headers):
    # The following set of fields should be present as headers in the uploaded file.
    required_fields = {u'company name'}
    # The following set of fields are optional.
    optional_fields = {u'website', u'email address', u'phone number', u'twitter', u'address', u'postal code', u'city'}

    # The following headers are present in the uploaded file.
    available_in_upload = set(headers)

    optional_in_upload = optional_fields & available_in_upload
    extra_in_upload = available_in_upload - (required_fields | optional_fields)

    company_name = row.get(u'company name')

    website = None
    email_address = None
    phone_number = None
    twitter = None
    address = None
    try:
        # Use atomic to rollback all intermediate database actions if an error occurs in just one of them.
        with transaction.atomic():
            description = ''
            # All the extra fields that are present in the upload are placed in the description field.
            for field in extra_in_upload:
                description += '{0}: {1}\n'.format(field, row.get(field))

            # Not using get_or_create() to make use of the skip_signal construction.
            try:
                account = Account.objects.get(name=company_name, tenant_id=tenant_id)
                if description:
                    new_description = '{0}\n{1}'.format(account.description.strip(), description)
                    account.description = new_description
                    account.skip_signal = True
                    account.save()
            except Account.DoesNotExist:
                account_status = AccountStatus.objects.get(name='Relation', tenant_id=tenant_id)
                account = Account(
                    name=company_name,
                    tenant_id=tenant_id,
                    status=account_status,
                    description=description
                )
                account.skip_signal = True
                account.save()

            if u'website' in optional_in_upload and row.get(u'website'):
                website = Website(
                    website=row.get(u'website'),
                    is_primary=True, account=account,
                    tenant_id=tenant_id
                )
                website.skip_signal = True
                website.save()

            if u'email address' in optional_in_upload and row.get(u'email address'):
                formatted_email_address = row.get(u'email address').lower()
                if not account.email_addresses.filter(email_address=formatted_email_address).exists():
                    email_address = EmailAddress(
                        email_address=formatted_email_address,
                        status=EmailAddress.PRIMARY_STATUS,
                        tenant_id=tenant_id
                    )
                    email_address.skip_signal = True
                    email_address.save()

            if u'phone number' in optional_in_upload and row.get(u'phone number'):
                formatted_phone_number = parse_phone_number(row.get(u'phone number'))
                phone_number = PhoneNumber(
                    number=formatted_phone_number,
                    tenant_id=tenant_id
                )
                phone_number.skip_signal = True
                phone_number.save()

            if u'twitter' in optional_in_upload and row.get(u'twitter'):
                twitter = SocialMedia(
                    name='twitter',
                    username=row.get(u'twitter'),
                    profile_url='https://twitter.com/{0}'.format(row.get(u'twitter')),
                    tenant_id=tenant_id
                )
                twitter.skip_signal = True
                twitter.save()

            # An Address consists of multiple, optional fields. So create or update the instance.
            if u'address' in optional_in_upload and row.get(u'address'):
                address = Address(
                    address=row.get(u'address'),
                    type='visiting',
                    tenant_id=tenant_id
                )
                address.skip_signal = True
                address.save()

            if u'postal code' in optional_in_upload and row.get(u'postal code'):
                if address:
                    address.postal_code = row.get(u'postal code')
                else:
                    address = Address(
                        postal_code=row.get(u'postal code'),
                        type='visiting',
                        tenant_id=tenant_id
                    )
                address.skip_signal = True
                address.save()

            if u'city' in optional_in_upload and row.get(u'city'):
                if address:
                    address.city = row.get(u'city')
                else:
                    address = Address(
                        city=row.get(u'city'),
                        type='visiting',
                        tenant_id=tenant_id
                    )
                address.skip_signal = True
                address.save()

    except Exception as e:
        # On an exception all database actions are rolled back. Because of the skip_signal=True no data is added to the
        # search index.
        logger.error(u'Import error {} for {}'.format(e, company_name))
    else:
        if website:
            website.skip_signal = False
            website.save()
            account.websites.add(website)
        if email_address:
            email_address.skip_signal = False
            email_address.save()
            account.email_addresses.add(email_address)
        if phone_number:
            phone_number.skip_signal = False
            phone_number.save()
            account.phone_numbers.add(phone_number)
        if twitter:
            twitter.skip_signal = False
            twitter.save()
            account.social_media.add(twitter)
        if address:
            address.skip_signal = False
            address.save()
            account.addresses.add(address)

        account.skip_signal = False
        account.save()
コード例 #15
0
def new_or_existing_contact(row, tenant_id, optional_in_upload):
    """
    Determine if Lily needs to create a new contact with the given row or that it should update a current contact.
    """
    account = None
    email_address = None
    formatted_phone_number = None

    first_name = row.get(u'first name')
    last_name = row.get(u'last name')

    if u'company name' in optional_in_upload and row.get(u'company name'):
        company_name = row.get(u'company name')
        try:
            account = Account.objects.get(name=company_name, tenant_id=tenant_id, is_deleted=False)
        except Account.DoesNotExist:
            pass

    if u'email address' in optional_in_upload and row.get(u'email address'):
        email_address = row.get(u'email address').lower()

    if u'phone number' in optional_in_upload and row.get(u'phone number'):
        formatted_phone_number = parse_phone_number(row.get(u'phone number'))

    # Regard as a existing contact when there is one in the database with the given name in combination with the
    # email address and / or phone number.
    qs = Contact.objects.filter(
        first_name=first_name,
        last_name=last_name,
        tenant_id=tenant_id,
        is_deleted=False
    )

    if account:
        qs = qs.filter(
            functions__account=account
        )

    if email_address and formatted_phone_number:
        qs = qs.filter(
            Q(email_addresses__email_address=email_address) | Q(phone_numbers__number=formatted_phone_number)
        )
    elif email_address:
        qs = qs.filter(email_addresses__email_address=email_address)
    elif formatted_phone_number:
        qs = qs.filter(phone_numbers__number=formatted_phone_number)

    contact = qs.first()

    if not contact:
        # There was no existing contact, so instantiate a new one.
        contact = Contact(
            first_name=first_name,
            last_name=last_name,
            tenant_id=tenant_id
        )

    # Skip the signal at this moment, so on a rollback the instance isn't still in the search index.
    contact.skip_signal = True

    return contact
コード例 #16
0
    def set_view_output(self):
        """
        Create a generic json format for account information based on the json from Dataprovider.
        """
        phone_number_limit = 5
        email_limit = 5
        address_limit = 3

        # Expected api output is json
        self.api_output = json.loads(self.api_output)

        # Return 404 when the api returned an error
        if self.api_output.get('error'):
            raise Http404()

        # Return error message when nothing was found
        if self.api_output.get('total') == 0:
            raise Exception(
                _('I\'m so sorry, I couldn\'t find any data for this website.')
            )

        # Filter useful data
        result = self.api_output['data'][0]

        # Get company name
        company = result.get('company')

        # Get website description
        description = result.get('description')

        # Get the keywords and convert to list
        tags = result.get('keywords')
        if tags:
            tags = result.get('keywords').strip().rstrip(',').split(',')

        # Get email addresses and convert to a list if needed
        emails = result.get('emailaddresses', []) or []
        if not isinstance(emails, list):
            emails = [emails]

        # Determine primary email since Dataprovider doesn't provide it
        primary_email = None
        if emails:
            primary_email = self._get_primary_email(emails)

            # Set primary email to the first in the list
            emails.index(primary_email)
            emails.remove(primary_email)
            emails.insert(0, primary_email)

        # Limit number of emails
        emails = emails[:email_limit]

        phone_numbers = []

        # Get primary phone number and convert to a nicer representation
        phone_number = result.get('phonenumber')

        if phone_number:
            phone_number = parse_phone_number(phone_number)
            phone_numbers.append(phone_number)

        # Get phone numbers and convert to list if needed
        raw_phone_numbers = result.get('phonenumbers', []) or []
        if not isinstance(raw_phone_numbers, list):
            raw_phone_numbers = [raw_phone_numbers]

        # Convert all phone numbers to a nicer representation
        for raw_phone_number in raw_phone_numbers:
            phone_numbers.append(parse_phone_number(raw_phone_number))

        # Limit number of phonenumbers
        phone_numbers = phone_numbers[:phone_number_limit]

        # Get what kind of company it is (e.g. LLC)
        legalentity = result.get('legalentity')

        # Get the VAT (Value Added Tax) identifaction number
        taxnumber = result.get('taxnumber')

        # Get bank account number
        bankaccountnumber = result.get('bankaccountnumber')

        # Get the CoC (Chamber of Commerce) number
        cocnumber = result.get('cocnumber')

        # Get the IBAN (Internation Bank Account Number)
        iban = result.get('iban')

        # Get the BIC (Bank Identifier Code)
        bic = result.get('bic')

        # Try to parse the address
        address = result.get('address')
        if address:
            street, street_number, complement = parse_address(address)
        else:
            street, street_number, complement = None, None, None

        # Make the full address
        addresses = []
        if address or result.get('city') or result.get(
                'zipcode') or result.get('country'):
            addresses = [{
                'street': street,
                'street_number': street_number,
                'complement': complement,
                'city': result.get('city'),
                'country': result.get('country'),
                'postal_code': result.get('zipcode'),
            }]

        addresses = addresses[:address_limit]

        # Build dict with account information
        self.view_output = {
            'name': company,
            'description': description,
            'tags': tags,
            'email_addresses': emails,
            'primary_email': primary_email,
            'phone_numbers': phone_numbers,
            'phone_number': phone_number,
            'addresses': addresses,
            'legalentity': legalentity,
            'taxnumber': taxnumber,
            'bankaccountnumber': bankaccountnumber,
            'cocnumber': cocnumber,
            'iban': iban,
            'bic': bic,
        }

        return json.dumps(self.view_output)
コード例 #17
0
ファイル: views.py プロジェクト: rmoorman/hellolily
    def set_view_output(self):
        """
        Create a generic json format for account information based on the json from Dataprovider.
        """
        # Expected api output is json
        self.api_output = anyjson.deserialize(self.api_output)

        # Return 404 when the api returned an error
        if self.api_output.get('error'):
            raise Http404()

        # Return error message when nothing was found
        if self.api_output.get('total') == 0:
            raise Exception(_('I\'m so sorry, I couldn\'t find any data for this website.'))

        # Filter useful data
        result = self.api_output['data'][0]

        # Get company name
        company = result.get('company')

        # Get website description
        description = result.get('description')

        # Get the keywords and convert to list
        tags = result.get('keywords')
        if tags:
            tags = result.get('keywords').strip().rstrip(',').split(',')

        # Get email addresses and convert to a list if needed
        emails = result.get('emailaddresses', []) or []
        if not isinstance(emails, list):
            emails = [emails]

        # Determine primary email since Dataprovider doesn't provide it
        primary_email = None
        if emails:
            primary_email = self.get_primary_email(emails)

        # Get phone numbers and convert to list if needed
        raw_phone_numbers = result.get('phonenumbers', []) or []
        if not isinstance(raw_phone_numbers, list):
            raw_phone_numbers = [raw_phone_numbers]

        # Convert all phone numbers to a nicer representation
        phone_numbers = []
        for raw_phone_number in raw_phone_numbers:
            phone_numbers.append(parse_phone_number(raw_phone_number))

        # Get primary phone number and convert to a nicer representation
        phone_number = result.get('phonenumber')
        if phone_number:
            phone_number = parse_phone_number(result.get('phonenumber'))

        # Get what kind of company it is (e.g. LLC)
        legalentity = result.get('legalentity')

        # Get the VAT (Value Added Tax) identifaction number
        taxnumber = result.get('taxnumber')

        # Get bank account number
        bankaccountnumber = result.get('bankaccountnumber')

        # Get the CoC (Chamber of Commerce) number
        cocnumber = result.get('cocnumber')

        # Get the IBAN (Internation Bank Account Number)
        iban = result.get('iban')

        # Get the BIC (Bank Identifier Code)
        bic = result.get('bic')

        # Try to parse the address
        address = result.get('address')
        if address:
            street, street_number, complement = parse_address(address)
        else:
            street, street_number, complement = None, None, None

        # Make the full address
        addresses = []
        if address or result.get('city') or result.get('zipcode') or result.get('country'):
            addresses = [{
                'street': street,
                'street_number': street_number,
                'complement': complement,
                'city': result.get('city'),
                'country': result.get('country'),
                'postal_code': result.get('zipcode'),
            }]

        # Build dict with account information
        self.view_output = {
            'name': company,
            'description': description,
            'tags': tags,
            'emails': emails,
            'primary_email': primary_email,
            'phone_numbers': phone_numbers,
            'phone_number': phone_number,
            'addresses': addresses,
            'legalentity': legalentity,
            'taxnumber': taxnumber,
            'bankaccountnumber': bankaccountnumber,
            'cocnumber': cocnumber,
            'iban': iban,
            'bic': bic,
        }

        return anyjson.serialize(self.view_output)
コード例 #18
0
    def _get_account_information(self, api_output):
        """
        Create a dict with account information based on the json response from Dataprovider.
        """
        phone_number_limit = 5
        email_limit = 5
        address_limit = 3

        # Expected API output is json.
        api_output_json = json.loads(api_output)

        # Return 404 when the api returned an error.
        if api_output_json.get('error'):
            raise Http404(api_output_json.get('error'))

        # Return error message when nothing was found.
        if api_output_json.get('total') == 0:
            raise APIException(_('I\'m so sorry, I couldn\'t find any data for this website.'))

        # Filter useful data.
        result = api_output_json['data'][0]

        # Get the keywords and convert to list.
        tags = result.get('keywords')
        if tags:
            tags = result.get('keywords').strip().rstrip(',').split(',')

        # Get email addresses as a list.
        emails = list(result.get('emailaddresses', []))

        # Determine primary email since Dataprovider doesn't provide it.
        primary_email = None
        if emails:
            primary_email = self._get_primary_email(emails)

            # Set primary email to the first in the list.
            emails.index(primary_email)
            emails.remove(primary_email)
            emails.insert(0, primary_email)

        phone_numbers = []

        # Get primary phone number and convert to a nicer representation.
        phone_number = result.get('phonenumber')

        if phone_number:
            phone_number = parse_phone_number(phone_number)
            phone_numbers.append(phone_number)

        # Get phone numbers as a list.
        raw_phone_numbers = list(result.get('phonenumbers', []))

        # Convert all phone numbers to a nicer representation.
        for raw_phone_number in raw_phone_numbers:
            phone_numbers.append(parse_phone_number(raw_phone_number))

        # Try to parse the address.
        address = result.get('address')
        address_line = ''
        if address:
            # Construct address_line, instead of assigning address to address_line directly,
            # because parse_address() also santizes the result.
            street, street_number, complement = parse_address(address)
            if street:
                address_line = street
            if street_number:
                address_line += ' ' + street_number
            if complement:
                address_line += complement

        # Make the full address.
        addresses = []
        if address or result.get('city') or result.get('zipcode') or result.get('country'):
            addresses = [{
                'address': address_line,
                'city': result.get('city'),
                'country': result.get('country'),
                'postal_code': result.get('zipcode'),
            }]

        # Get social media profiles.
        social_profiles = result.get('socialprofiles')

        # Group profiles by platform.
        # Disregards the other platforms provided by Dataprovider: Facebook, Google Plus and Pinterest.
        social_media = {}
        for profile in social_profiles:
            if profile.startswith('twitter.com/'):
                if 'twitter' not in social_media:
                    social_media['twitter'] = []
                social_media['twitter'].append(profile)
            elif profile.startswith('www.linkedin.com/in/'):
                if 'linkedin' not in social_media:
                    social_media['linkedin'] = []
                social_media['linkedin'].append(profile)

        primary_twitter = ''
        if 'twitter' in social_media:
            primary_twitter = self._get_primary_profile(social_media['twitter'], result.get('company'))

        primary_linkedin = ''
        if 'linkedin' in social_media:
            primary_linkedin = self._get_primary_profile(social_media['linkedin'], result.get('company'))

        # Build dict with account information.
        account_information = {
            'name': result.get('company'),
            'description': result.get('description'),
            'tags': tags,
            'email_addresses': emails[:email_limit],
            'primary_email': primary_email,
            'phone_numbers': phone_numbers[:phone_number_limit],
            'phone_number': phone_number,
            'addresses': addresses[:address_limit],
            'legalentity': result.get('legalentity'),
            'taxnumber': result.get('taxnumber'),
            'bankaccountnumber': result.get('bankaccountnumber'),
            'cocnumber': result.get('cocnumber'),
            'iban': result.get('iban'),
            'bic': result.get('bic'),
            'social_media_profiles': social_media,
            'twitter': primary_twitter,
            'linkedin': primary_linkedin,
        }

        return account_information
コード例 #19
0
    def _get_account_information(self, json):
        """
        Create a dict with account information based on the json response from Dataprovider.
        """
        phone_number_limit = 5
        email_limit = 5
        address_limit = 3

        # Return 404 when the api returned an error.
        if json.get('error'):
            raise Http404(json.get('error'))

        if json.get('total') == 0:
            # No results from Dataprovider so return an empty list.
            return []

        # Filter useful data.
        try:
            # Lookup API returns data as a dict.
            result = json['data'][0]
        except (KeyError, IndexError):
            # Enrich API returns a single hit.
            result = json['data']

        if not result:
            # No results from Dataprovider so return an empty list.
            return []

        # Get the keywords and convert to list.
        tags = result.get('keywords')
        if tags:
            tags = [tag.strip() for tag in tags.split(',')]
            tags = filter(None, tags)  # Remove empty tags.

        # Get email addresses as a list.
        emails = list(result.get('emailaddresses', []))

        # Determine primary email since Dataprovider doesn't provide it.
        primary_email = None
        if emails:
            primary_email = self._get_primary_email(emails)

            # Set primary email to the first in the list.
            emails.index(primary_email)
            emails.remove(primary_email)
            emails.insert(0, primary_email)

        phone_numbers = []

        # Get primary phone number and convert to a nicer representation.
        phone_number = result.get('phonenumber')

        if phone_number:
            phone_number = parse_phone_number(phone_number)
            phone_numbers.append(phone_number)

        # Get phone numbers as a list.
        raw_phone_numbers = list(result.get('phonenumbers', []))

        # Convert all phone numbers to a nicer representation.
        for raw_phone_number in raw_phone_numbers:
            phone_numbers.append(parse_phone_number(raw_phone_number))

        # Try to parse the address.
        address = result.get('address')
        address_line = ''
        if address:
            # Construct address_line, instead of assigning address to address_line directly,
            # because parse_address() also santizes the result.
            street, street_number, complement = parse_address(address)
            if street:
                address_line = street
            if street_number:
                address_line += ' ' + street_number
            if complement:
                address_line += complement

        # Make the full address.
        addresses = []
        if address or result.get('city') or result.get('zipcode') or result.get('country'):
            # There are some exceptions on the country codes, so make sure results of Dataprovider conform to the
            # ISO 3166-1 alpha-2 standard we use.
            mapping = {
                'UK': 'GB',
                'EL': 'GR',
            }
            country = mapping.get(result.get('country'), result.get('country')) if result.get('country') else ''
            addresses = [{
                'address': address_line,
                'city': result.get('city', ''),
                'country': country,
                'postal_code': result.get('zipcode', ''),
            }]

        # Get social media profiles.
        social_profiles = result.get('socialprofiles')

        # Group profiles by platform.
        # Disregards the other platforms provided by Dataprovider: Facebook, Google Plus and Pinterest.
        social_media = {}
        if social_profiles:
            for profile in social_profiles:
                if profile.startswith('twitter.com/'):
                    if 'twitter' not in social_media:
                        social_media['twitter'] = []
                    social_media['twitter'].append(profile)
                elif profile.startswith('www.linkedin.com/in/'):
                    if 'linkedin' not in social_media:
                        social_media['linkedin'] = []
                    social_media['linkedin'].append(profile)

        primary_twitter = ''
        if 'twitter' in social_media:
            primary_twitter = self._get_primary_profile(social_media['twitter'], result.get('company'))

        primary_linkedin = ''
        if 'linkedin' in social_media:
            primary_linkedin = self._get_primary_profile(social_media['linkedin'], result.get('company'))

        description = result.get('description')

        website = result.get('hostname')

        # Build dict with account information.
        account_information = {
            'name': result.get('company'),
            'description': description,
            'tags': tags,
            'email_addresses': emails[:email_limit],
            'primary_email': primary_email,
            'phone_numbers': phone_numbers[:phone_number_limit],
            'phone_number': phone_number,
            'addresses': addresses[:address_limit],
            'legalentity': result.get('legalentity'),
            'taxnumber': result.get('taxnumber'),
            'bankaccountnumber': result.get('bankaccountnumber'),
            'cocnumber': result.get('cocnumber'),
            'iban': result.get('iban'),
            'bic': result.get('bic'),
            'social_media_profiles': social_media,
            'twitter': primary_twitter,
            'linkedin': primary_linkedin,
            'primary_website': website,
        }

        return account_information
コード例 #20
0
    def _get_account_information(self, api_output):
        """
        Create a dict with account information based on the json response from Dataprovider.
        """
        phone_number_limit = 5
        email_limit = 5
        address_limit = 3

        # Expected API output is json.
        api_output_json = json.loads(api_output)

        # Return 404 when the api returned an error.
        if api_output_json.get('error'):
            raise Http404(api_output_json.get('error'))

        # Return error message when nothing was found.
        if api_output_json.get('total') == 0:
            raise APIException(
                _('I\'m so sorry, I couldn\'t find any data for this website.')
            )

        # Filter useful data.
        result = api_output_json['data'][0]

        # Get the keywords and convert to list.
        tags = result.get('keywords')
        if tags:
            tags = result.get('keywords').strip().rstrip(',').split(',')

        # Get email addresses as a list.
        emails = list(result.get('emailaddresses', []))

        # Determine primary email since Dataprovider doesn't provide it.
        primary_email = None
        if emails:
            primary_email = self._get_primary_email(emails)

            # Set primary email to the first in the list.
            emails.index(primary_email)
            emails.remove(primary_email)
            emails.insert(0, primary_email)

        phone_numbers = []

        # Get primary phone number and convert to a nicer representation.
        phone_number = result.get('phonenumber')

        if phone_number:
            phone_number = parse_phone_number(phone_number)
            phone_numbers.append(phone_number)

        # Get phone numbers as a list.
        raw_phone_numbers = list(result.get('phonenumbers', []))

        # Convert all phone numbers to a nicer representation.
        for raw_phone_number in raw_phone_numbers:
            phone_numbers.append(parse_phone_number(raw_phone_number))

        # Try to parse the address.
        address = result.get('address')
        address_line = ''
        if address:
            # Construct address_line, instead of assigning address to address_line directly,
            # because parse_address() also santizes the result.
            street, street_number, complement = parse_address(address)
            if street:
                address_line = street
            if street_number:
                address_line += ' ' + street_number
            if complement:
                address_line += complement

        # Make the full address.
        addresses = []
        if address or result.get('city') or result.get(
                'zipcode') or result.get('country'):
            addresses = [{
                'address': address_line,
                'city': result.get('city'),
                'country': result.get('country'),
                'postal_code': result.get('zipcode'),
            }]

        # Get social media profiles.
        social_profiles = result.get('socialprofiles')

        # Group profiles by platform.
        # Disregards the other platforms provided by Dataprovider: Facebook, Google Plus and Pinterest.
        social_media = {}
        for profile in social_profiles:
            if profile.startswith('twitter.com/'):
                if 'twitter' not in social_media:
                    social_media['twitter'] = []
                social_media['twitter'].append(profile)
            elif profile.startswith('www.linkedin.com/in/'):
                if 'linkedin' not in social_media:
                    social_media['linkedin'] = []
                social_media['linkedin'].append(profile)

        primary_twitter = ''
        if 'twitter' in social_media:
            primary_twitter = self._get_primary_profile(
                social_media['twitter'], result.get('company'))

        primary_linkedin = ''
        if 'linkedin' in social_media:
            primary_linkedin = self._get_primary_profile(
                social_media['linkedin'], result.get('company'))

        # Build dict with account information.
        account_information = {
            'name': result.get('company'),
            'description': result.get('description'),
            'tags': tags,
            'email_addresses': emails[:email_limit],
            'primary_email': primary_email,
            'phone_numbers': phone_numbers[:phone_number_limit],
            'phone_number': phone_number,
            'addresses': addresses[:address_limit],
            'legalentity': result.get('legalentity'),
            'taxnumber': result.get('taxnumber'),
            'bankaccountnumber': result.get('bankaccountnumber'),
            'cocnumber': result.get('cocnumber'),
            'iban': result.get('iban'),
            'bic': result.get('bic'),
            'social_media_profiles': social_media,
            'twitter': primary_twitter,
            'linkedin': primary_linkedin,
        }

        return account_information
コード例 #21
0
    def create(self, request, *args, **kwargs):
        """
        Sends a websocket message to the user with the corresponding internal number
        """
        response = super(CallViewSet, self).create(request, *args, **kwargs)
        called_user = LilyUser.objects.filter(
            internal_number=request.data['internal_number'],
            tenant_id=request.user.tenant_id
        ).first()

        if not called_user:
            return response

        caller_number = parse_phone_number(request.data['caller_number'])
        result = search_number(called_user.tenant_id, caller_number)
        search_data = result.get('data', {})
        accounts = search_data['accounts']
        contacts = search_data['contacts']

        # If a single accounts with this number has been found, show information about and link to this account.
        if accounts and len(accounts) == 1:
            data = {
                'destination': 'account',
                'icon': static('app/images/notification_icons/account.png'),
                'params': {
                    'name': accounts[0].name,
                    'number': caller_number,
                    'id': accounts[0].id,
                },
            }

            # If there are also contacts, change the title. If there's only one contact, we prepend this contacts
            # name, else we append "Somebody from"
            if contacts:
                if len(contacts) > 1:
                    data['params']['name'] = 'Somebody from %s' % data['params']['name']
                else:
                    data['params']['name'] = '%s from %s' % (contacts[0].full_name, data['params']['name'])

        # If there are contacts but no accounts, show information about and link to the first contact.
        elif contacts:
            data = {
                'destination': 'contact',
                'icon': static('app/images/notification_icons/contact.png'),
                'params': {
                    'name': contacts[0].full_name,
                    'number': caller_number,
                    'id': contacts[0].id,
                },
            }

        # If no account or contact has been found, use the name provided by VoIPGRID.
        else:
            data = {
                'destination': 'create',
                'icon': static('app/images/notification_icons/add-account.png'),
                'params': {
                    'name': request.data.get('caller_name'),
                    'number': caller_number,
                },
            }

        # Sends the data as a notification event to the user who picked up the phone.
        Group('user-%s' % called_user.id).send({
            'text': json.dumps({
                'event': 'notification',
                'data': data,
            }),
        })

        return response
コード例 #22
0
ファイル: views.py プロジェクト: Vegulla/hellolily
    def set_view_output(self):
        """
        Create a generic json format for account information based on the json from Dataprovider.
        """
        phone_number_limit = 5
        email_limit = 5
        address_limit = 3

        # Expected api output is json
        self.api_output = json.loads(self.api_output)

        # Return 404 when the api returned an error
        if self.api_output.get("error"):
            raise Http404()

        # Return error message when nothing was found
        if self.api_output.get("total") == 0:
            raise Exception(_("I'm so sorry, I couldn't find any data for this website."))

        # Filter useful data
        result = self.api_output["data"][0]

        # Get company name
        company = result.get("company")

        # Get website description
        description = result.get("description")

        # Get the keywords and convert to list
        tags = result.get("keywords")
        if tags:
            tags = result.get("keywords").strip().rstrip(",").split(",")

        # Get email addresses and convert to a list if needed
        emails = result.get("emailaddresses", []) or []
        if not isinstance(emails, list):
            emails = [emails]

        # Determine primary email since Dataprovider doesn't provide it
        primary_email = None
        if emails:
            primary_email = self._get_primary_email(emails)

            # Set primary email to the first in the list
            emails.index(primary_email)
            emails.remove(primary_email)
            emails.insert(0, primary_email)

        # Limit number of emails
        emails = emails[:email_limit]

        phone_numbers = []

        # Get primary phone number and convert to a nicer representation
        phone_number = result.get("phonenumber")

        if phone_number:
            phone_number = parse_phone_number(phone_number)
            phone_numbers.append(phone_number)

        # Get phone numbers and convert to list if needed
        raw_phone_numbers = result.get("phonenumbers", []) or []
        if not isinstance(raw_phone_numbers, list):
            raw_phone_numbers = [raw_phone_numbers]

        # Convert all phone numbers to a nicer representation
        for raw_phone_number in raw_phone_numbers:
            phone_numbers.append(parse_phone_number(raw_phone_number))

        # Limit number of phonenumbers
        phone_numbers = phone_numbers[:phone_number_limit]

        # Get what kind of company it is (e.g. LLC)
        legalentity = result.get("legalentity")

        # Get the VAT (Value Added Tax) identifaction number
        taxnumber = result.get("taxnumber")

        # Get bank account number
        bankaccountnumber = result.get("bankaccountnumber")

        # Get the CoC (Chamber of Commerce) number
        cocnumber = result.get("cocnumber")

        # Get the IBAN (Internation Bank Account Number)
        iban = result.get("iban")

        # Get the BIC (Bank Identifier Code)
        bic = result.get("bic")

        # Try to parse the address
        address = result.get("address")
        if address:
            street, street_number, complement = parse_address(address)
        else:
            street, street_number, complement = None, None, None

        # Make the full address
        addresses = []
        if address or result.get("city") or result.get("zipcode") or result.get("country"):
            addresses = [
                {
                    "street": street,
                    "street_number": street_number,
                    "complement": complement,
                    "city": result.get("city"),
                    "country": result.get("country"),
                    "postal_code": result.get("zipcode"),
                }
            ]

        addresses = addresses[:address_limit]

        # Build dict with account information
        self.view_output = {
            "name": company,
            "description": description,
            "tags": tags,
            "email_addresses": emails,
            "primary_email": primary_email,
            "phone_numbers": phone_numbers,
            "phone_number": phone_number,
            "addresses": addresses,
            "legalentity": legalentity,
            "taxnumber": taxnumber,
            "bankaccountnumber": bankaccountnumber,
            "cocnumber": cocnumber,
            "iban": iban,
            "bic": bic,
        }

        return json.dumps(self.view_output)