সেট আপ করুন এবং পুশ বিজ্ঞপ্তি গ্রহণ করুন

ফর্মের ডেটা পরিবর্তিত হলে নোটিফিকেশন পেতে আপনি 'Watches' কালেকশনের পদ্ধতিগুলো ব্যবহার করতে পারেন। এই পৃষ্ঠায় পুশ নোটিফিকেশন সেট আপ করা ও গ্রহণ করার জন্য একটি ধারণাগত রূপরেখা এবং নির্দেশাবলী দেওয়া হয়েছে।

সংক্ষিপ্ত বিবরণ

গুগল ফর্মস এপিআই-এর পুশ নোটিফিকেশন ফিচারটি অ্যাপ্লিকেশনগুলোকে ফর্মের ডেটা পরিবর্তনের ক্ষেত্রে নোটিফিকেশন পাওয়ার জন্য সাবস্ক্রাইব করার সুযোগ দেয়। নোটিফিকেশনগুলো সাধারণত পরিবর্তনের কয়েক মিনিটের মধ্যেই একটি ক্লাউড পাব/সাব টপিকে পাঠানো হয়।

পুশ নোটিফিকেশন পেতে হলে, আপনাকে একটি ক্লাউড পাব/সাব টপিক সেট আপ করতে হবে এবং উপযুক্ত ইভেন্ট টাইপের জন্য ওয়াচ তৈরি করার সময় সেই টপিকের নামটি প্রদান করতে হবে।

এই ডকুমেন্টেশনে ব্যবহৃত মূল ধারণাগুলোর সংজ্ঞা নিচে দেওয়া হলো:

  • টার্গেট হলো এমন একটি স্থান যেখানে নোটিফিকেশন পাঠানো হয়। একমাত্র সমর্থিত টার্গেট হলো একটি ক্লাউড পাব/সাব টপিক।
  • ইভেন্ট টাইপ হলো নোটিফিকেশনের একটি বিভাগ, যেটিতে কোনো থার্ড-পার্টি অ্যাপ্লিকেশন সাবস্ক্রাইব করতে পারে।
  • ওয়াচ হলো ফর্মস এপিআই-কে দেওয়া একটি নির্দেশ, যার মাধ্যমে কোনো নির্দিষ্ট ফর্মের একটি নির্দিষ্ট ইভেন্ট টাইপের জন্য নোটিফিকেশন কোনো টার্গেট- এর কাছে পৌঁছে দেওয়া হয়।

একবার আপনি কোনো নির্দিষ্ট ফর্মে কোনো ইভেন্ট টাইপের জন্য একটি ওয়াচ তৈরি করলে, সেই ওয়াচের টার্গেট (যা একটি ক্লাউড পাব/সাব টপিক) ওয়াচটির মেয়াদ শেষ না হওয়া পর্যন্ত সেই ফর্মের ইভেন্টগুলো থেকে নোটিফিকেশন পেতে থাকে। আপনার ওয়াচটি এক সপ্তাহ স্থায়ী হয়, কিন্তু এর মেয়াদ শেষ হওয়ার আগে যেকোনো সময়ে watches.renew() -এ একটি রিকোয়েস্ট পাঠিয়ে আপনি এর মেয়াদ বাড়াতে পারেন।

আপনার ক্লাউড পাব/সাব টপিক শুধুমাত্র সেই ফর্মগুলির বিজ্ঞপ্তি পায় যা আপনি আপনার সরবরাহ করা ক্রেডেনশিয়াল দিয়ে দেখতে পারেন। উদাহরণস্বরূপ, যদি ব্যবহারকারী আপনার অ্যাপ্লিকেশন থেকে অনুমতি প্রত্যাহার করে নেয় বা পর্যবেক্ষণাধীন কোনো ফর্ম সম্পাদনা করার অ্যাক্সেস হারায়, তাহলে আর বিজ্ঞপ্তি পাঠানো হয় না।

উপলব্ধ ইভেন্টের প্রকারগুলি

গুগল ফর্মস এপিআই বর্তমানে দুই ধরনের ইভেন্ট অফার করে:

  • 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"
}

একটি ক্লাউড পাব/সাব টপিক সেট আপ করুন

নোটিফিকেশনগুলো ক্লাউড পাব/সাব টপিকে পাঠানো হয়। ক্লাউড পাব/সাব থেকে, আপনি একটি ওয়েব হুকের মাধ্যমে অথবা একটি সাবস্ক্রিপশন এন্ডপয়েন্ট পোল করে নোটিফিকেশন পেতে পারেন।

একটি ক্লাউড পাব/সাব টপিক সেট আপ করতে, নিম্নলিখিতগুলি করুন:

  1. ক্লাউড পাব/সাব-এর পূর্বশর্তগুলো সম্পূর্ণ করুন।
  2. একটি ক্লাউড পাব/সাব ক্লায়েন্ট সেট আপ করুন
  3. ক্লাউড পাব/সাব-এর মূল্যতালিকা পর্যালোচনা করুন এবং আপনার গুগল ক্লাউড কনসোল প্রজেক্টের জন্য বিলিং চালু করুন।
  4. তিনটি উপায়ের যেকোনো একটিতে একটি ক্লাউড পাব/সাব টপিক তৈরি করুন:

  5. আপনার নোটিফিকেশনগুলো কীভাবে পাঠানো হবে, তা Cloud Pub/Sub-কে জানানোর জন্য সেখানে একটি সাবস্ক্রিপশন তৈরি করুন

  6. অবশেষে, আপনার টপিককে লক্ষ্য করে ওয়াচ তৈরি করার আগে, আপনাকে ফর্মস নোটিফিকেশন সার্ভিস অ্যাকাউন্টকে (forms-notifications@system.gserviceaccount.com) আপনার টপিকে পাবলিশ করার অনুমতি দিতে হবে।

একটি ঘড়ি তৈরি করুন

একবার আপনার কাছে এমন একটি টপিক থাকলে যেখানে ফর্মস এপিআই পুশ নোটিফিকেশন সার্ভিস অ্যাকাউন্টটি পাবলিশ করতে পারে, আপনি watches.create() মেথড ব্যবহার করে নোটিফিকেশন তৈরি করতে পারবেন। এই মেথডটি যাচাই করে যে প্রদত্ত ক্লাউড পাব/সাব টপিকটি পুশ নোটিফিকেশন সার্ভিস অ্যাকাউন্ট দ্বারা অ্যাক্সেসযোগ্য কিনা, এবং যদি এটি টপিকটি অ্যাক্সেস করতে না পারে তবে এটি ব্যর্থ হয়; উদাহরণস্বরূপ, যদি টপিকটি বিদ্যমান না থাকে বা আপনি সেই টপিকে পাবলিশ করার অনুমতি না দিয়ে থাকেন।

পাইথন

forms/snippets/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)

নোড.জেএস

forms/snippets/create_watch.js
import path from 'node:path';
import {authenticate} from '@google-cloud/local-auth';
import {forms} from '@googleapis/forms';

// TODO: Replace with a valid form ID.
const formID = '<YOUR_FORM_ID>';

/**
 * Creates a watch on a form to get notifications for new responses.
 */
async function createWatch() {
  // Authenticate with Google and get an authorized client.
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Forms API client.
  const formsClient = forms({
    version: 'v1',
    auth: authClient,
  });

  // The request body to create a watch.
  const watchRequest = {
    watch: {
      target: {
        topic: {
          // TODO: Replace with a valid Cloud Pub/Sub topic name.
          topicName: 'projects/<YOUR_TOPIC_PATH>',
        },
      },
      // The event type to watch for. 'RESPONSES' is the only supported type.
      eventType: 'RESPONSES',
    },
  };

  // Send the request to create the watch.
  const result = await formsClient.forms.watches.create({
    formId: formID,
    requestBody: watchRequest,
  });

  console.log(result.data);
  return result.data;
}

একটি ঘড়ি মুছুন

পাইথন

forms/snippets/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)

নোড.জেএস

forms/snippets/delete_watch.js
import path from 'node:path';
import {authenticate} from '@google-cloud/local-auth';
import {forms} from '@googleapis/forms';

// TODO: Replace with a valid form ID.
const formID = '<YOUR_FORM_ID>';
// TODO: Replace with a valid watch ID.
const watchID = '<YOUR_FORMS_WATCH_ID>';

/**
 * Deletes a watch from a form.
 */
async function deleteWatch() {
  // Authenticate with Google and get an authorized client.
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Forms API client.
  const formsClient = forms({
    version: 'v1',
    auth: authClient,
  });

  // Send the request to delete the watch.
  const result = await formsClient.forms.watches.delete({
    formId: formID,
    watchId: watchID,
  });

  console.log(result.data);
  return result.data;
}

অনুমোদন

ফর্মস এপিআই-এর সমস্ত কলের মতোই, watches.create() কলগুলোকেও একটি অথরাইজেশন টোকেন দিয়ে অনুমোদিত করতে হবে। টোকেনটিতে অবশ্যই এমন একটি স্কোপ অন্তর্ভুক্ত থাকতে হবে যা নোটিফিকেশন পাঠানো হচ্ছে এমন ডেটা পড়ার অ্যাক্সেস প্রদান করে।

  • স্কিমা পরিবর্তনের ক্ষেত্রে, এর অর্থ হলো এমন যেকোনো স্কোপ যা forms.get() ব্যবহার করে ফর্মগুলিতে পঠন অ্যাক্সেস প্রদান করে।
  • রেসপন্স-এর ক্ষেত্রে, এর অর্থ হলো এমন যেকোনো স্কোপ যা ফর্মের রেসপন্সগুলো পড়ার অ্যাক্সেস দেয়, উদাহরণস্বরূপ forms.responses.list() ব্যবহার করে।

নোটিফিকেশন পাঠানোর জন্য, অ্যাপ্লিকেশনটিকে অবশ্যই অনুমোদিত ব্যবহারকারীর কাছ থেকে প্রয়োজনীয় স্কোপসহ একটি OAuth গ্রান্ট ধরে রাখতে হবে। যদি ব্যবহারকারী অ্যাপ্লিকেশনটি থেকে সংযোগ বিচ্ছিন্ন করে, তাহলে নোটিফিকেশন আসা বন্ধ হয়ে যায় এবং একটি ত্রুটির কারণে ওয়াচটি স্থগিত হয়ে যেতে পারে। পুনরায় অনুমোদন পাওয়ার পর নোটিফিকেশন আবার চালু করতে, ‘রিনিউ এ ওয়াচ’ দেখুন।

একটি ফর্মের ঘড়িগুলো তালিকাভুক্ত করুন

পাইথন

forms/snippets/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)

নোড.জেএস

forms/snippets/list_watches.js
import path from 'node:path';
import {authenticate} from '@google-cloud/local-auth';
import {forms} from '@googleapis/forms';

// TODO: Replace with a valid form ID.
const formID = '<YOUR_FORM_ID>';

/**
 * Lists the watches for a given form.
 */
async function listWatches() {
  // Authenticate with Google and get an authorized client.
  const auth = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/forms.responses.readonly',
  });

  // Create a new Forms API client.
  const formsClient = forms({
    version: 'v1',
    auth,
  });

  // Get the list of watches for the form.
  const result = await formsClient.forms.watches.list({
    formId: formID,
  });

  console.log(result.data);
  return result.data;
}

ঘড়ি নবায়ন করুন

পাইথন

forms/snippets/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)

নোড.জেএস

forms/snippets/renew_watch.js
import path from 'node:path';
import {authenticate} from '@google-cloud/local-auth';
import {forms} from '@googleapis/forms';

// TODO: Replace with a valid form ID.
const formID = '<YOUR_FORM_ID>';
// TODO: Replace with a valid watch ID.
const watchID = '<YOUR_FORMS_WATCH_ID>';

/**
 * Renews a watch on a form.
 */
async function renewWatch() {
  // Authenticate with Google and get an authorized client.
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Forms API client.
  const formsClient = forms({
    version: 'v1',
    auth: authClient,
  });

  // Send the request to renew the watch.
  const result = await formsClient.forms.watches.renew({
    formId: formID,
    watchId: watchID,
  });

  console.log(result.data);
  return result.data;
}

থ্রটলিং

নোটিফিকেশনের সংখ্যা সীমিত—প্রতিটি ঘড়ি প্রতি ত্রিশ সেকেন্ডে সর্বোচ্চ একটি নোটিফিকেশন পেতে পারে। নোটিফিকেশনের এই সীমা পরিবর্তন সাপেক্ষ।

থ্রটলিং-এর কারণে, একটিমাত্র নোটিফিকেশন একাধিক ইভেন্টের সাথে সম্পর্কিত হতে পারে। অন্য কথায়, একটি নোটিফিকেশন নির্দেশ করে যে শেষ নোটিফিকেশনটির পর এক বা একাধিক ইভেন্ট ঘটেছে।

সীমা

যেকোনো সময়ে, একটি নির্দিষ্ট ফর্ম এবং ইভেন্ট টাইপের জন্য, প্রতিটি ক্লাউড কনসোল প্রজেক্টে নিম্নলিখিত বিষয়গুলো থাকতে পারে:

  • মোট ২০টি পর্যন্ত ঘড়ি
  • প্রতি ব্যবহারকারী সর্বোচ্চ একটি ঘড়ি

এছাড়াও, যেকোনো সময়ে, সমস্ত ক্লাউড কনসোল প্রজেক্ট জুড়ে প্রতিটি ফর্ম প্রতি ইভেন্ট টাইপের জন্য মোট ৫০টি ওয়াচে সীমাবদ্ধ থাকবে।

যখন কোনো এন্ড ইউজারের ক্রেডেনশিয়াল ব্যবহার করে একটি ওয়াচ তৈরি বা নবায়ন করা হয়, তখন সেটি সেই ইউজারের সাথে যুক্ত হয়। যদি যুক্ত এন্ড ইউজার ফর্মটিতে অ্যাক্সেস হারান অথবা অ্যাপটির অ্যাক্সেস প্রত্যাহার করে নেন, তাহলে ওয়াচটি সাসপেন্ড হয়ে যায়।

নির্ভরযোগ্যতা

ব্যতিক্রমী পরিস্থিতি ছাড়া অন্য সব ক্ষেত্রে, প্রতিটি ঘটনার পর প্রত্যেক প্রহরীকে অন্তত একবার অবহিত করা হয়। অধিকাংশ ক্ষেত্রেই, কোনো ঘটনা ঘটার কয়েক মিনিটের মধ্যেই বিজ্ঞপ্তিটি পৌঁছে দেওয়া হয়।

ত্রুটি

যদি কোনো ওয়াচের নোটিফিকেশন ক্রমাগত ডেলিভার হতে ব্যর্থ হয়, তাহলে ওয়াচটির স্টেট SUSPENDED হয়ে যায় এবং ওয়াচটির errorType ফিল্ডটি সেট হয়ে যায়। একটি সাসপেন্ডেড ওয়াচের স্টেট ACTIVE এ রিসেট করতে এবং নোটিফিকেশন পুনরায় চালু করতে, “Renew a watch” দেখুন।

প্রস্তাবিত ব্যবহার

  • একাধিক ওয়াচের লক্ষ্য হিসেবে একটিমাত্র ক্লাউড পাব/সাব টপিক ব্যবহার করুন।
  • কোনো টপিকের উপর নোটিফিকেশন পাওয়ার সময়, ফর্ম আইডিটি নোটিফিকেশন পেলোডে অন্তর্ভুক্ত থাকে। কোন ডেটা এবং কোন ফর্ম থেকে তা আনতে হবে, তা জানার জন্য ইভেন্ট টাইপের সাথে এটি ব্যবহার করুন।
  • EventType.RESPONSES সহ একটি নোটিফিকেশনের পরে আপডেট করা ডেটা পেতে, forms.responses.list() কল করুন।
    • অনুরোধে ফিল্টারটি timestamp > timestamp_of_the_last_response_you_fetched এ সেট করুন।
  • EventType.SCHEMA সহ একটি নোটিফিকেশনের পরে আপডেট করা ডেটা আনতে, forms.get() কল করুন।