Есть ли способ получить идентификатор ресурса Google People API из идентификатора контакта Google Contacts?

Мы храним contactId пользователя в нашей базе данных и используем его для получения / редактирования / удаления контактов, когда пользователь запрашивает из нашего приложения. Теперь, когда Google Contacts API должен быть закрыт, нам нужно вызвать Google People API для этих действий, используя идентификатор ресурса.

Есть ли способ получить идентификатор ресурса Google People API из контактного идентификатора Google Контактов?

Я нашел следующий ответ в Stackoverflow:

API контактов и API людей - это отдельные API, не предназначенные для взаимодействия друг с другом.

Тем не менее, обратный инженерный способ сделать это - взять идентификатор контакта API контактов, проанализировать это шестнадцатеричное значение, преобразовать его в десятичное и добавить к нему префикс «c», и он станет идентификатором ресурса People API.

например если идентификатор контакта API контактов был 100, то идентификатор человека API людей был бы c256. Когда вы таким образом выбираете контакты из People API, у него будет информация объединенного профиля, если таковая имеется.

Я попробовал решение, и оно работает, но нужно знать, можем ли мы использовать это преобразование без ошибок (то есть без каких-либо исключений) для заполнения соответствующего идентификатора ресурса в идентификаторе контакта.


person Ranjani    schedule 04.05.2021    source источник


Ответы (2)


Отвечать:

Хотя обходной путь, представленный в этом ответе, кажется, работает, я думаю, что есть более документированный способ найти resourceName People API на основе contactId .

Этот contactId является частью ресурса Person, если соединение исходит от CONTACTS.

В частности, эту информацию можно найти как часть ресурса по адресу:

{
  "resourceName": "people/c...",
  "metadata": {
    "sources": [
      {
        "type": "CONTACT",
        "id": "CONTACT_ID" // Converting to decimal and adding "people/c" results in resource name
      }
    ]
  }
}

Следовательно, если у вас есть массив действительных contactId, вы можете найти соответствующий resourceNames, перечислив свои подключения (см. people.connections.list) и проверяет, совпадает ли contactId с id во вложенном поле, и получает resourceName для этого соединения, если это так.

Пример кода:

Например, используя скрипт приложений, вы можете получить сопоставление contactId и resourceName, например:

function getResourceNamesFromContactIds(contactIds) { // contactIds: array with valid contactIds
  const resourceName = "people/me";
  const optionalArgs = {
    personFields: "metadata",
    sources: "READ_SOURCE_TYPE_CONTACT"
  }
  const connections = People.People.Connections.list(resourceName, optionalArgs)["connections"];
  const mapping = contactIds.map(contactId => {
    const foundConnection = connections.find(connection => {
      return contactId == connection["metadata"]["sources"][0]["id"];
    });
    if (foundConnection) {
      return {
        contactId: contactId,
        resourceName: foundConnection["resourceName"]
      }
    }
  }).filter(el => el);
  return mapping;  
}
person Iamblichus    schedule 04.05.2021
comment
Спасибо за ответ. Мы действительно видели, что параметр источников People API содержит contactId. Но в нашем случае мы будем вызывать API редактирования / удаления с синхронизацией планировщика. Итак, мы ищем способ получить сопоставление идентификатора контакта - идентификатора ресурса, прежде чем перемещать наших пользователей в People API. Также получение идентификатора ресурса без вызова какого-либо API будет для нас лучшим вариантом, поскольку 1. Каждый пользователь может иметь до 25 тысяч контактов. Максимальный лимит people.connections.list - 1000. Итак, это 25 звонков на 1 пользователя. 2. У нас около 15 тысяч пользователей, поэтому количество обращений к API будет расти экспоненциально. - person Ranjani; 04.05.2021
comment
Итак, если преобразование в десятичное число и добавление людей / c приводит к получению имени ресурса, можем ли мы продолжить? - person Ranjani; 04.05.2021
comment
@Ranjani Если вы не хотите использовать People API, я думаю, что преобразование в десятичное будет вашим лучшим вариантом. Это не задокументировано, но, похоже, работает. - person Iamblichus; 04.05.2021
comment
Если я использую это преобразование для сопоставления идентификатора контакта - идентификатора ресурса, вернет ли оно правильный идентификатор ресурса для всех идентификаторов контактов? Или будет поломка для любого набора пользователей? - person Ranjani; 04.05.2021
comment
@Ranjani Ну, шестнадцатеричное-десятичное преобразование вроде работает, но, поскольку оно не задокументировано, оно может измениться без предварительного уведомления. Я думаю, что предложенное мной преобразование безопаснее, поскольку оно основано на задокументированном персональном ресурсе People API. Конечно, вы всегда можете проверить, действительно ли полученное имя ресурса после преобразования в десятичную дробь, но для этого в любом случае потребуется использование API. - person Iamblichus; 04.05.2021
comment
@Ranjani Примите этот ответ (stackoverflow.com/help/someone-answers). - person Iamblichus; 07.05.2021

Принятый ответ не работает для контактов, у которых нет адресов электронной почты.

Нет необходимости получать объект метаданных из person.emailAddresses, мы можем получить его непосредственно из объекта person, который не требует наличия каких-либо других полей в информации о человеке.

Кроме того, принятый ответ предполагает, что первый источник всегда имеет тип CONTACT, что может быть не так, и в этом случае вы можете получить неправильный идентификатор контакта.

Вот улучшенная версия (на Java):

List<Person> people = getPeople();// fetch all pages of the user contacts, with "personFields" set to "metadata" only.

Map<String, String> mapping = new HashMap<>();

people.forEach(person -> {
    PersonMetadata metadata = person.getMetadata();
    if (metadata != null) {
        List<Source> sources = metadata.getSources();
        if (sources != null) {
            sources.stream()
                .filter(srcObj -> "CONTACT".equalsIgnoreCase(srcObj.getType()))
                .findFirst()
                .ifPresent(source ->
                    mapping.put(source.getId(), person.getResourceName()));
        }
    }
});
person marmor    schedule 11.05.2021
comment
Да, я не заметил, что metadata является действительным personField, спасибо за это. Также sources можно использовать при отправке запроса, нет необходимости фильтровать его после получения ответа. Наконец, обратите внимание, что приведенный мной пример скрипта приложений является всего лишь примером. Пользователь не запрашивал конкретный код, просто если есть способ получить эту информацию. - person Iamblichus; 11.05.2021
comment
Кроме того, преобразование шестнадцатеричного числа в десятичное работает даже для контактов, у которых нет адресов электронной почты. Я спросил об этом в Google, и мне сказали, что я могу использовать хак для одноразовой миграции, если я сделаю преобразование в течение следующего месяца. После этого они не могут сказать, останется ли он неизменным. - person Ranjani; 12.05.2021