def process_user(target_user, filtered_calendars):
    filtered_calendar_by_email_dict = dict(zip(map(get('resource_email'), filtered_calendars), filtered_calendars))
    contacts_client = contacts(email=target_user, options=options())

    if options().undo:
        undo(contacts_client, target_user, ContactsFeed)
        return

    # Get Contacts Groups for user
    groups = contacts_client.get_groups().entry

    # Find Contact Group by extended property
    magic_group = get_magic_group(groups) or create_magic_group(contacts_client)
    magic_group_members = get_group_members(contacts_client, magic_group)
    magic_group_emails_set = map(get('address'), flatmap(get('email'), magic_group_members))

    # Find "My Contacts" group in Contacts
    my_contacts_group = next(iter(
        filter(lambda group: group.system_group and group.system_group.id == options().my_contacts_id, groups)), None)

    logging.info('%s: Using group called "%s" with %d members and ID %s',
        target_user, magic_group.title.text, len(magic_group_members),
        magic_group.id.text)

    # Add new Calendar Resources as Contacts
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for cal in filter(lambda x: \
                x.resource_email not in magic_group_emails_set, filtered_calendars):
            new_contact = calendar_resource_to_contact(cal)

            # Add Contact to the relevant groups
            new_contact.group_membership_info.append(GroupMembershipInfo(href=magic_group.id.text))
            if options().my_contacts and my_contacts_group:
                new_contact.group_membership_info.append(GroupMembershipInfo(href=my_contacts_group.id.text))

            # Set Contact extended property
            extprop = ExtendedProperty()
            extprop.name = options().contact_extended_property_name
            extprop.value = options().contact_extended_property_value
            new_contact.extended_property.append(extprop)

            logging.debug('%s: Creating contact "%s"', target_user,
                    new_contact.name.full_name.text)
            batch.put('add_insert', new_contact)

    # Sync data for existing Calendar Resources that were added by the script. Remove those that have been deleted
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for existing_contact in filter(is_script_contact, magic_group_members):
            calendar_resource_to_copy = get_value_by_contact_email(filtered_calendar_by_email_dict, existing_contact)

            if calendar_resource_to_copy:
                calendar_contact = calendar_resource_to_contact(calendar_resource_to_copy)
                if sync_contact(calendar_contact, existing_contact):
                    logging.info('%s: Modifying contact "%s" with ID %s',
                        target_user, existing_contact.name.full_name.text, existing_contact.id.text)
                    batch.put('add_update', existing_contact)
            elif options().delete_old:
                logging.info('%s: Removing surplus auto-generated contact "%s" with ID %s',
                    target_user, existing_contact.name.full_name.text, existing_contact.id.text)
                batch.put('add_delete', existing_contact)
def process_user(target_user, filtered_calendars):
    filtered_calendar_by_email_dict = dict(
        zip(map(get('resource_email'), filtered_calendars),
            filtered_calendars))
    contacts_client = contacts(email=target_user, options=options())

    if options().undo:
        undo(contacts_client, target_user, ContactsFeed)
        return

    # Get Contacts Groups for user
    groups = contacts_client.get_groups().entry

    # Find Contact Group by extended property
    magic_group = get_magic_group(groups) or create_magic_group(
        contacts_client)
    magic_group_members = get_group_members(contacts_client, magic_group)
    magic_group_emails_set = map(get('address'),
                                 flatmap(get('email'), magic_group_members))

    # Find "My Contacts" group in Contacts
    my_contacts_group = next(
        iter(
            filter(
                lambda group: group.system_group and group.system_group.id ==
                options().my_contacts_id, groups)), None)

    logging.info('%s: Using group called "%s" with %d members and ID %s',
                 target_user, magic_group.title.text, len(magic_group_members),
                 magic_group.id.text)

    # Add new Calendar Resources as Contacts
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for cal in filter(lambda x: \
                x.resource_email not in magic_group_emails_set, filtered_calendars):
            new_contact = calendar_resource_to_contact(cal)

            # Add Contact to the relevant groups
            new_contact.group_membership_info.append(
                GroupMembershipInfo(href=magic_group.id.text))
            if options().my_contacts and my_contacts_group:
                new_contact.group_membership_info.append(
                    GroupMembershipInfo(href=my_contacts_group.id.text))

            # Set Contact extended property
            extprop = ExtendedProperty()
            extprop.name = options().contact_extended_property_name
            extprop.value = options().contact_extended_property_value
            new_contact.extended_property.append(extprop)

            logging.debug('%s: Creating contact "%s"', target_user,
                          new_contact.name.full_name.text)
            batch.put('add_insert', new_contact)

    # Sync data for existing Calendar Resources that were added by the script. Remove those that have been deleted
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for existing_contact in filter(is_script_contact, magic_group_members):
            calendar_resource_to_copy = get_value_by_contact_email(
                filtered_calendar_by_email_dict, existing_contact)

            if calendar_resource_to_copy:
                calendar_contact = calendar_resource_to_contact(
                    calendar_resource_to_copy)
                if sync_contact(calendar_contact, existing_contact):
                    logging.info('%s: Modifying contact "%s" with ID %s',
                                 target_user,
                                 existing_contact.name.full_name.text,
                                 existing_contact.id.text)
                    batch.put('add_update', existing_contact)
            elif options().delete_old:
                logging.info(
                    '%s: Removing surplus auto-generated contact "%s" with ID %s',
                    target_user, existing_contact.name.full_name.text,
                    existing_contact.id.text)
                batch.put('add_delete', existing_contact)
def process_target_user(target_user_email, users_to_copy,
                        user_to_copy_by_ldap_dict):
    contacts_client = contacts(email=target_user_email, options=options())

    if options().undo:
        undo(contacts_client, target_user_email, ContactsFeed)
        return

    users_groups = contacts_client.get_groups().entry

    # Find group by extended property
    magic_group = get_magic_group(users_groups) or create_magic_group(
        contacts_client)
    magic_group_members = get_group_members(contacts_client, magic_group)
    magic_group_ldaps_set = lambda: filter(None, [
        get_ldap_id_contact(contact) for contact in magic_group_members
    ])

    # Find "My Contacts" group in Contacts
    my_contacts_group = next(
        iter(
            filter(
                lambda group: group.system_group and group.system_group.id ==
                options().my_contacts_id, users_groups)), None)

    logging.info('%s: Using group called "%s" with %d members and ID %s',
                 target_user_email, magic_group.title.text,
                 len(magic_group_members), magic_group.id.text)

    # remove all existing contacts
    if options().delete_contacts:
        with closing(Batch(contacts_client, ContactsFeed)) as batch:
            for existing_contact in filter(is_script_contact,
                                           magic_group_members):
                logging.info('%s: Removing contact "%s" with ID %s',
                             target_user_email,
                             existing_contact.name.full_name.text,
                             existing_contact.id.text)
                batch.put('add_delete', existing_contact)

    # Check dangling entries in scripted group (extended_property only held 'google_apps_sync' Employee ID)
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for dangling_contact in filter(
                lambda contact: not is_script_contact(contact),
                magic_group_members):
            logging.info('%s: Removing dangling contact "%s" with ID %s',
                         target_user_email,
                         dangling_contact.name.full_name.text,
                         dangling_contact.id.text)
            batch.put('add_delete', dangling_contact)

    # Add new users (not already in the group) as contacts
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for user_to_copy in users_to_copy:
            if get_ldap_id_json(user_to_copy) not in magic_group_ldaps_set():
                new_contact = json_to_contact_object(user_to_copy)

                # Add the relevant groups
                new_contact.group_membership_info.append(
                    GroupMembershipInfo(href=magic_group.id.text))
                if options().my_contacts and my_contacts_group:
                    new_contact.group_membership_info.append(
                        GroupMembershipInfo(href=my_contacts_group.id.text))

                # Set extended properties
                new_contact.extended_property.append(
                    ExtendedProperty(
                        name=options().contact_id_extended_property_name,
                        value=get_ldap_id_json(user_to_copy)))
                new_contact.extended_property.append(
                    ExtendedProperty(
                        name=options().contact_extended_property_name,
                        value=options().contact_extended_property_value))

                logging.debug('%s: Creating contact "%s"', target_user_email,
                              new_contact.name.full_name.text)
                batch.put('add_insert', new_contact)

    # Sync data for existing contacts that were added by the script and remove those that have been deleted
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for existing_contact in filter(is_script_contact, magic_group_members):
            if get_ldap_id_contact(
                    existing_contact) in user_to_copy_by_ldap_dict:
                user_to_copy = user_to_copy_by_ldap_dict[get_ldap_id_contact(
                    existing_contact)]
                modified = False

                if options().rename_old and is_renamed_contact(
                        existing_contact):
                    # Remove renamed flag
                    remove_suffix(existing_contact)
                    modified = True

                # Sync data
                dir_contact = json_to_contact_object(user_to_copy)
                modified = sync_contact(dir_contact,
                                        existing_contact) or modified

                if modified:
                    logging.info('%s: Modifying contact "%s" with ID %s',
                                 target_user_email,
                                 existing_contact.name.full_name.text,
                                 existing_contact.id.text)
                    batch.put('add_update', existing_contact)
            else:
                if options().delete_old:
                    logging.info(
                        '%s: Removing surplus auto-generated contact "%s" with ID %s',
                        target_user_email,
                        existing_contact.name.full_name.text,
                        existing_contact.id.text)
                    batch.put('add_delete', existing_contact)
                elif options(
                ).rename_old and not is_renamed_contact(existing_contact):
                    old_name = existing_contact.name.full_name.text
                    add_suffix(existing_contact)
                    logging.info(
                        '%s: Renaming surplus auto-generated contact "%s" to "%s" with ID %s',
                        target_user_email, old_name,
                        existing_contact.name.full_name.text,
                        existing_contact.id.text)
                    batch.put('add_update', existing_contact)
def process_target_user(target_user_email, users_to_copy, user_to_copy_by_ldap_dict):
    contacts_client = contacts(email=target_user_email, options=options())

    if options().undo:
        undo(contacts_client, target_user_email, ContactsFeed)
        return
    
    users_groups = contacts_client.get_groups().entry

    # Find group by extended property
    magic_group = get_magic_group(users_groups) or create_magic_group(contacts_client)
    magic_group_members = get_group_members(contacts_client, magic_group)
    magic_group_ldaps_set = lambda: filter(None, [ get_ldap_id_contact(contact) for contact in magic_group_members ])

    # Find "My Contacts" group in Contacts
    my_contacts_group = next(iter(
        filter(lambda group: group.system_group and group.system_group.id == options().my_contacts_id, users_groups)), None)

    logging.info('%s: Using group called "%s" with %d members and ID %s',
        target_user_email, magic_group.title.text,
        len(magic_group_members), magic_group.id.text)

    # remove all existing contacts
    if options().delete_contacts:
        with closing(Batch(contacts_client, ContactsFeed)) as batch:
            for existing_contact in filter(is_script_contact, magic_group_members):
                logging.info('%s: Removing contact "%s" with ID %s', target_user_email, existing_contact.name.full_name.text, existing_contact.id.text)
                batch.put('add_delete', existing_contact)

    # Check dangling entries in scripted group (extended_property only held 'google_apps_sync' Employee ID)
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for dangling_contact in filter(lambda contact: not is_script_contact(contact), magic_group_members):
            logging.info('%s: Removing dangling contact "%s" with ID %s',
                        target_user_email, dangling_contact.name.full_name.text, dangling_contact.id.text)
            batch.put('add_delete', dangling_contact)

    # Add new users (not already in the group) as contacts
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for user_to_copy in users_to_copy:
            if get_ldap_id_json(user_to_copy) not in magic_group_ldaps_set():
                new_contact = json_to_contact_object(user_to_copy)
                
                # Add the relevant groups
                new_contact.group_membership_info.append(GroupMembershipInfo(href=magic_group.id.text))
                if options().my_contacts and my_contacts_group:
                    new_contact.group_membership_info.append(GroupMembershipInfo(href=my_contacts_group.id.text))
                
                # Set extended properties
                new_contact.extended_property.append(ExtendedProperty(name=options().contact_id_extended_property_name, value=get_ldap_id_json(user_to_copy)))
                new_contact.extended_property.append(ExtendedProperty(name=options().contact_extended_property_name, value=options().contact_extended_property_value))

                logging.debug('%s: Creating contact "%s"',
                    target_user_email, new_contact.name.full_name.text)
                batch.put('add_insert', new_contact)
    
    # Sync data for existing contacts that were added by the script and remove those that have been deleted
    with closing(Batch(contacts_client, ContactsFeed)) as batch:
        for existing_contact in filter(is_script_contact, magic_group_members):
            if get_ldap_id_contact(existing_contact) in user_to_copy_by_ldap_dict:
                user_to_copy = user_to_copy_by_ldap_dict[get_ldap_id_contact(existing_contact)]
                modified = False

                if options().rename_old and is_renamed_contact(existing_contact):
                    # Remove renamed flag
                    remove_suffix(existing_contact)
                    modified = True

                # Sync data
                dir_contact = json_to_contact_object(user_to_copy)
                modified = sync_contact(dir_contact, existing_contact) or modified

                if modified:
                    logging.info('%s: Modifying contact "%s" with ID %s',
                        target_user_email, existing_contact.name.full_name.text, existing_contact.id.text)
                    batch.put('add_update', existing_contact)
            else:
                if options().delete_old:
                    logging.info('%s: Removing surplus auto-generated contact "%s" with ID %s',
                        target_user_email, existing_contact.name.full_name.text, existing_contact.id.text)
                    batch.put('add_delete', existing_contact)
                elif options().rename_old and not is_renamed_contact(existing_contact):
                    old_name = existing_contact.name.full_name.text
                    add_suffix(existing_contact)
                    logging.info('%s: Renaming surplus auto-generated contact "%s" to "%s" with ID %s',
                        target_user_email, old_name, existing_contact.name.full_name.text, existing_contact.id.text)
                    batch.put('add_update', existing_contact)