Настройте и получайте push-уведомления

Вы можете использовать методы коллекции Watches для получения уведомлений при изменении данных в формах. На этой странице представлен концептуальный обзор и инструкции по настройке и получению push-уведомлений.

Обзор

Функция push-уведомлений Google Forms API позволяет приложениям подписываться на уведомления при изменении данных в формах. Уведомления доставляются в тему Cloud Pub/Sub обычно в течение нескольких минут после изменения.

Чтобы получать push-уведомления, вам необходимо настроить тему Cloud Pub/Sub и указать имя этой темы при создании наблюдения для соответствующего типа событий.

Ниже приведены определения ключевых понятий, используемых в этой документации:

  • Цель — это место, куда отправляются уведомления. Единственная поддерживаемая цель — тема Cloud Pub/Sub.
  • Тип события — это категория уведомлений, на которые может подписаться стороннее приложение.
  • Отслеживание — это инструкция API Forms по доставке уведомлений о событиях определенного типа в определенной форме в целевой объект .

После того как вы создадите наблюдение для типа события в определенной форме, цель этого наблюдения (то есть тема Cloud Pub/Sub) будет получать уведомления об этих событиях в этой форме до тех пор, пока не истечет срок наблюдения. Срок действия ваших часов составляет неделю, но вы можете продлить их в любой момент до истечения срока их действия, отправив запрос в watch.renew() .

Ваша тема Cloud Pub/Sub получает уведомления только о формах, которые вы можете просмотреть с предоставленными вами учетными данными. Например, если пользователь отзовет разрешение вашего приложения или потеряет доступ к редактированию просматриваемой формы, уведомления больше не будут доставляться.

Доступные типы событий

API Google Forms в настоящее время предлагает две категории событий:

  • EventType.SCHEMA , который уведомляет об изменениях содержимого и настроек формы.
  • EventType.RESPONSES , который уведомляет об отправке ответов формы (как новых, так и обновленных).

Ответы на уведомления

Уведомления кодируются с помощью JSON и содержат:

  • Идентификатор триггерной формы
  • Идентификатор запускающих часов
  • Тип события, вызвавшего уведомление
  • Другие поля, заданные Cloud Pub/Sub, например messageId publishTime

Уведомления не содержат подробной формы или данных ответа. После получения каждого уведомления требуется отдельный вызов API для получения свежих данных. См. «Рекомендации по использованию» , чтобы узнать, как это сделать.

В следующем фрагменте показан пример уведомления об изменении схемы:

{
  "attributes": {
    "eventType": "SCHEMA",
    "formId": "18Xgmr4XQb-l0ypfCNGQoHAw2o82foMr8J0HPHdagS6g",
    "watchId": "892515d1-a902-444f-a2fe-42b718fe8159"
  },
  "messageId": "767437830649",
  "publishTime": "2021-03-31T01:34:08.053Z"
}

В следующем фрагменте показан пример уведомления о новом ответе:

{
  "attributes": {
    "eventType": "RESPONSES",
    "formId": "18Xgmr4XQb-l0ypfCNGQoHAw2o82foMr8J0HPHdagS6g",
    "watchId": "5d7e5690-b1ff-41ce-8afb-b469912efd7d"
  },
  "messageId": "767467004397",
  "publishTime": "2021-03-31T01:43:57.285Z"
}

Настройте тему Cloud Pub/Sub

Уведомления доставляются в темы Cloud Pub/Sub. Из Cloud Pub/Sub вы можете получать уведомления через веб-перехватчик или путем опроса конечной точки подписки.

Чтобы настроить тему Cloud Pub/Sub, выполните следующие действия:

  1. Выполните необходимые условия для Cloud Pub/Sub .
  2. Настройте клиент Cloud Pub/Sub .
  3. Ознакомьтесь с ценами на Cloud Pub/Sub и включите оплату для своего проекта Developer Console.
  4. Создайте тему Cloud Pub/Sub одним из трех способов:

  5. Создайте подписку в Cloud Pub/Sub, чтобы указать Cloud Pub/Sub, как доставлять ваши уведомления.

  6. Наконец, прежде чем создавать часы, ориентированные на вашу тему, вам необходимо предоставить учетной записи службы уведомлений Forms (forms-notifications@system.gserviceaccount.com) разрешение на публикацию в вашей теме.

Создать часы

Если у вас есть тема, в которой учетная запись службы push-уведомлений Forms API может публиковать, вы можете создавать уведомления с помощью метода watch.create() . Этот метод проверяет, что указанная тема Cloud Pub/Sub доступна для учетной записи службы push-уведомлений, и завершается сбоем, если она не может достичь темы; например, если тема не существует или вы не предоставили ей разрешение на публикацию этой темы.

Питон

формы/фрагменты/create_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secret.json", SCOPES)
  creds = tools.run_flow(flow, store)

service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

watch = {
    "watch": {
        "target": {"topic": {"topicName": "<YOUR_TOPIC_PATH>"}},
        "eventType": "RESPONSES",
    }
}

form_id = "<YOUR_FORM_ID>"

# Print JSON response after form watch creation
result = service.forms().watches().create(formId=form_id, body=watch).execute()
print(result)

Node.js

формы/фрагменты/create_watch.js
'use strict';

const path = require('path');
const google = require('@googleapis/forms');
const {authenticate} = require('@google-cloud/local-auth');

const formID = '<YOUR_FORM_ID>';

async function runSample(query) {
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const forms = google.forms({
    version: 'v1',
    auth: authClient,
  });
  const watchRequest = {
    watch: {
      target: {
        topic: {
          topicName: 'projects/<YOUR_TOPIC_PATH>',
        },
      },
      eventType: 'RESPONSES',
    },
  };
  const res = await forms.forms.watches.create({
    formId: formID,
    requestBody: watchRequest,
  });
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Удалить часы

Питон

формы/фрагменты/delete_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secret.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"
watch_id = "<YOUR_WATCH_ID>"

# Print JSON response after deleting a form watch
result = (
    service.forms().watches().delete(formId=form_id, watchId=watch_id).execute()
)
print(result)

Node.js

формы/фрагменты/delete_watch.js
'use strict';

const path = require('path');
const google = require('@googleapis/forms');
const {authenticate} = require('@google-cloud/local-auth');

const formID = '<YOUR_FORM_ID>';
const watchID = '<YOUR_FORMS_WATCH_ID>';

async function runSample(query) {
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const forms = google.forms({
    version: 'v1',
    auth: authClient,
  });
  const res = await forms.forms.watches.delete({
    formId: formID,
    watchId: watchID,
  });
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Авторизация

Как и все вызовы Forms API, вызовы watches.create() должны быть авторизованы с помощью токена авторизации. Токен должен включать область, предоставляющую доступ для чтения к данным, о которых отправляются уведомления.

  • Для изменений схемы это означает любую область, которая предоставляет доступ для чтения к формам через form.get() .
  • Для ответов это означает любую область, которая предоставляет доступ для чтения к ответам формы , например, через form.responses.list() .

Для доставки уведомлений приложение должно сохранить разрешение OAuth от авторизованного пользователя с необходимыми областями. Если пользователь отключит приложение, уведомления прекратятся, а часы могут быть приостановлены с ошибкой. Чтобы возобновить уведомления после восстановления авторизации, см. Продление часов .

Получение списка часов формы

Питон

формы/фрагменты/list_watches.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secrets.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"

# Print JSON list of form watches
result = service.forms().watches().list(formId=form_id).execute()
print(result)

Node.js

формы/фрагменты/list_watches.js
'use strict';

const path = require('path');
const google = require('@googleapis/forms');
const {authenticate} = require('@google-cloud/local-auth');

const formID = '<YOUR_FORM_ID>';

async function runSample(query) {
  const auth = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/forms.responses.readonly',
  });
  const forms = google.forms({
    version: 'v1',
    auth: auth,
  });
  const res = await forms.forms.watches.list({formId: formID});
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Продлить часы

Питон

формы/фрагменты/renew_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secrets.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"
watch_id = "<YOUR_WATCH_ID>"

# Print JSON response after renewing a form watch
result = (
    service.forms().watches().renew(formId=form_id, watchId=watch_id).execute()
)
print(result)

Node.js

формы/фрагменты/renew_watch.js
'use strict';

const path = require('path');
const google = require('@googleapis/forms');
const {authenticate} = require('@google-cloud/local-auth');

const formID = '<YOUR_FORM_ID>';
const watchID = '<YOUR_FORMS_WATCH_ID>';

async function runSample(query) {
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const forms = google.forms({
    version: 'v1',
    auth: authClient,
  });
  const res = await forms.forms.watches.renew({
    formId: formID,
    watchId: watchID,
  });
  console.log(res.data);
  return res.data;
}

if (module === require.main) {
  runSample().catch(console.error);
}
module.exports = runSample;

Регулирование

Уведомления ограничены: каждые часы могут получать не более одного уведомления каждые тридцать секунд. Этот порог частоты может быть изменен.

Из-за регулирования одно уведомление может соответствовать нескольким событиям. Другими словами, уведомление указывает, что с момента последнего уведомления произошло одно или несколько событий.

Пределы

В любой момент для заданной формы и типа события каждый проект Cloud Console может иметь:

  • всего до 20 часов
  • до одного просмотра на конечного пользователя

Кроме того, в любой момент каждая форма ограничена 50 наблюдениями каждого типа событий во всех проектах Cloud Console.

Часы связываются с конечным пользователем, когда они создаются или обновляются с использованием учетных данных этого пользователя. Наблюдение приостанавливается, если связанный конечный пользователь теряет доступ к форме или отзывает доступ приложения к форме.

Надежность

Каждая вахта уведомляется по крайней мере один раз после каждого события во всех обстоятельствах, кроме чрезвычайных. В подавляющем большинстве случаев уведомление доставляется в течение нескольких минут после события.

Ошибки

Если уведомления для наблюдения постоянно не доставляются, состояние наблюдения становится SUSPENDED и устанавливается поле errorType для наблюдения. Чтобы сбросить состояние приостановленных часов на ACTIVE и возобновить уведомления, см. Продление часов .

Рекомендуемое использование

  • Используйте одну тему Cloud Pub/Sub в качестве цели для нескольких просмотров.
  • При получении уведомления по теме идентификатор формы включается в полезные данные уведомления. Используйте его с типом события, чтобы знать, какие данные следует извлечь и из какой формы их получить.
  • Чтобы получить обновленные данные после уведомления с помощью EventType.RESPONSES , вызовите form.responses.list() .
    • Установите фильтр запроса на timestamp > timestamp_of_the_last_response_you_fetched .
  • Чтобы получить обновленные данные после уведомления с помощью EventType.SCHEMA , вызовите form.get() .