如何通过 API 更改 google 头像?

How to change google profile picture via API?

我正在寻找一种如何以编程方式更改用户个人资料照片的方法。

一般来说,我需要能换域GSuite用户的头像,不过如果有API换自己的头像也不错

已经尝试过:

Contacts API,但我正在尝试更改我自己的(或假冒的)个人资料图片,所以我认为这 API 不适合我的情况。

如果您能指出我搜索的方向,我将非常高兴。我就是不相信没有办法换头像,不可能是真的。

更新:

已检查 Contact API - 也不起作用,看起来它只更改了我联系人列表中 me 的头像,其他人看不到更改,主要个人资料图片保留一样。

代码:

// admin directory way
const { google } = require('googleapis');
const SafeBase64 = require('url-safe-base64');
const GOOGLE = require(process.env.GOOGLEAPIS_VAULT);

const encodedPhoto = SafeBase64.encode('R0lGODdhBAAEAIABAAMA/////ywAAAAABAAEAAACBkRiYJgHBQA7');

const JWTClient = new google.auth.JWT(
  GOOGLE.client_email,
  null,
  GOOGLE.private_key,
  [
    'https://www.googleapis.com/auth/admin.directory.user',
  ],
  'gsync@***.com', // sub
);

const directory = google.admin({ version: 'directory_v1', auth: JWTClient });
directory.users.photos.update({}, ctx.params.email);
const res = await directory.users.photos.update({
  userKey: ctx.params.email,
  resource: {
    photoData: encodedPhoto,
  },
});
// Contacts API way
const { google } = require('googleapis');
const SafeBase64 = require('url-safe-base64');
const GOOGLE = require(process.env.GOOGLEAPIS_VAULT);

const JWTClient = new google.auth.JWT(
  GOOGLE.client_email,
  null,
  GOOGLE.private_key,
  [
    'https://www.google.com/m8/feeds/',
  ],
  ctx.params.email, //sub
);

const res1 = await JWTClient.requestAsync({
  headers: {
    'GData-Version': 3.0,
  },
  params: {
    alt: 'json',
    q: 'arsenyp@***.com',
  },
  url: `https://www.google.com/m8/feeds/contacts/${ctx.params.email}/full`,
});

const contactIdFull = res1.data.feed.entry.filter((c) => c.gd$email[0].address === ctx.params.email)[0].id.$t;
const [, contactId] = /\/base\/([a-z0-9]+)$/.exec(contactIdFull);

// https://www.google.com/m8/feeds/contacts/{userEmail}/full/{contactId}

const res2 = await JWTClient.requestAsync({
  headers: {
    'GData-Version': 3.0,
  },
  params: {
    alt: 'json',
  },
  url: `https://www.google.com/m8/feeds/contacts/${ctx.params.email}/full/${contactId}`,
});

const { href: image, gd$etag: etagJ } = res2.data.entry.link.filter((l) => l.rel === 'http://schemas.google.com/contacts/2008/rel#photo')[0];
const res3 = await axios({
  method: 'GET',
  url: image,
  headers: {
    Authorization: `Bearer "${(await JWTClient.getAccessTokenAsync()).token}"`,
  },
  responseType: 'arraybuffer',
});
const etag = JSON.parse(etagJ);

// PUT /m8/feeds/photos/media/default/contactId
// If-match: Etag
// Content-Type: image/*

const res4 = await axios({
  method: 'PUT',
  url: `https://www.google.com/m8/feeds/photos/media/default/${contactId}`,
  headers: {
    Authorization: `Bearer "${(await JWTClient.getAccessTokenAsync()).token}"`,
    'Content-Type': 'image/png',
  },
  // responseType: 'arraybuffer',
  data: Buffer.from('R0lGODdhBAAEAIABAAMA/////ywAAAAABAAEAAACBkRiYJgHBQA7', 'base64'),
});
// People API way (won't work, throwing an error)
const userId = '1024471xxxxx251564465';

const JWTClient = new google.auth.JWT(
  GOOGLE.client_email,
  null,
  GOOGLE.private_key,
  [
    'https://www.googleapis.com/auth/contacts',
    'profile',
  ],
  ctx.params.email, // sub
);

const people = google.people({ version: 'v1', auth: JWTClient });

const res = await people.people.updateContactPhoto({
  resourceName: `people/${userId}`,
  resource: {
    photoBytes: SafeBase64.encode('R0lGODdhBAAEAIABAAMA/////ywAAAAABAAEAAACBkRiYJgHBQA7'),
    personFields: 'photos',
  },
  sources: [
    'READ_SOURCE_TYPE_PROFILE',
  ],
});

好的,正如@Sudhakar 所说,没有这样的 API。

但我发现 admin 目录 API 实际上改变了大部分地方的配置文件。

技巧在于,用户需要手动从 https://aboutme.google.com/ Profile picture 中删除头像,因为这张照片相对于管理目录具有最高优先级。

如果用户从 aboutme.google.com 中删除照片,然后通过管理目录 v1 更改它 API 可以在日历、Gmail、通讯录中看到这张照片...

所以检查我的第一个代码示例:

// admin directory way
const { google } = require('googleapis');
const SafeBase64 = require('url-safe-base64');
const GOOGLE = require(process.env.GOOGLEAPIS_VAULT);

const encodedPhoto = SafeBase64.encode('R0lGODdhBAAEAIABAAMA/////ywAAAAABAAEAAACBkRiYJgHBQA7');
const targerUser = 'arsenyp@***.com';

const JWTClient = new google.auth.JWT(
  GOOGLE.client_email,
  null,
  GOOGLE.private_key,
  [
    'https://www.googleapis.com/auth/admin.directory.user',
  ],
  'gsync@***.com', // sub - this is service user with proper permissions, not a target user
);

const directory = google.admin({ version: 'directory_v1', auth: JWTClient });
directory.users.photos.update({}, targerUser);
const res = await directory.users.photos.update({
  userKey: targerUser,
  resource: {
    photoData: encodedPhoto,
  },
});