1. ভূমিকা
Google Chat অ্যাপগুলি আপনার পরিষেবা এবং সংস্থানগুলি সরাসরি Google Chat-এ নিয়ে আসে, ব্যবহারকারীদের তথ্য পেতে এবং কথোপকথন ছেড়ে না দিয়ে দ্রুত পদক্ষেপ নিতে দেয়।
এই কোডল্যাবে, আপনি Node.js এবং ক্লাউড ফাংশন ব্যবহার করে একটি পোল অ্যাপ তৈরি এবং স্থাপন করতে শিখবেন।
আপনি কি শিখবেন
- ক্লাউড শেল ব্যবহার করুন
- ক্লাউড ফাংশনে স্থাপন করুন
- স্ল্যাশ কমান্ড এবং ডায়ালগ সহ ব্যবহারকারীর ইনপুট পান
- ইন্টারেক্টিভ কার্ড তৈরি করুন
2. সেটআপ এবং প্রয়োজনীয়তা
একটি Google ক্লাউড প্রকল্প তৈরি করুন, তারপরে চ্যাট অ্যাপ ব্যবহার করবে এমন API এবং পরিষেবাগুলি সক্ষম করুন৷
পূর্বশর্ত
একটি Google Chat অ্যাপ তৈরি করার জন্য Google Chat-এ অ্যাক্সেস সহ একটি Google Workspace অ্যাকাউন্ট প্রয়োজন। আপনার যদি আগে থেকেই Google Workspace অ্যাকাউন্ট না থাকে, তাহলে এই কোডল্যাবের সাথে এগিয়ে যাওয়ার আগে একটি তৈরি করুন এবং সাইন-ইন করুন।
স্ব-গতিসম্পন্ন পরিবেশ সেটআপ
- Google ক্লাউড কনসোল খুলুন এবং একটি প্রকল্প তৈরি করুন।
প্রজেক্ট আইডিটি মনে রাখবেন, সমস্ত Google ক্লাউড প্রকল্প জুড়ে একটি অনন্য নাম (উপরের নামটি ইতিমধ্যে নেওয়া হয়েছে এবং আপনার জন্য কাজ করবে না, দুঃখিত!)। এটি পরে এই কোডল্যাবেPROJECT_ID
হিসাবে উল্লেখ করা হবে।
- এর পরে, Google ক্লাউড সংস্থানগুলি ব্যবহার করার জন্য, ক্লাউড কনসোলে বিলিং সক্ষম করুন ৷
এই কোডল্যাবের মাধ্যমে চালানোর জন্য খুব বেশি খরচ করা উচিত নয়, যদি কিছু থাকে। কোডল্যাবের শেষে "ক্লিন আপ" বিভাগে যে কোনও নির্দেশাবলী অনুসরণ করতে ভুলবেন না যা আপনাকে কীভাবে সংস্থানগুলি বন্ধ করতে হবে তা পরামর্শ দেয় যাতে আপনি এই টিউটোরিয়ালের বাইরে বিলিং করতে না পারেন৷ Google ক্লাউডের নতুন ব্যবহারকারীরা $300USD ফ্রি ট্রায়াল প্রোগ্রামের জন্য যোগ্য৷
গুগল ক্লাউড শেল
যদিও Google ক্লাউড আপনার ল্যাপটপ থেকে দূরবর্তীভাবে পরিচালিত হতে পারে, এই কোডল্যাবে আমরা Google Cloud Shell ব্যবহার করব, একটি কমান্ড লাইন পরিবেশ যা Google ক্লাউডে চলছে।
ক্লাউড শেল সক্রিয় করুন
- ক্লাউড কনসোল থেকে, ক্লাউড শেল সক্রিয় করুন ক্লিক করুন
.
আপনি যখন প্রথমবার ক্লাউড শেল খুলবেন, আপনাকে একটি বর্ণনামূলক স্বাগত বার্তা উপস্থাপন করা হবে। আপনি যদি স্বাগত বার্তাটি দেখতে পান তবে চালিয়ে যান ক্লিক করুন। স্বাগত বার্তা আবার প্রদর্শিত হয় না. এখানে স্বাগত বার্তা:
ক্লাউড শেলের সাথে সংযোগ করতে এবং সংযোগ করতে এটির মাত্র কয়েক মুহূর্ত লাগবে৷ সংযোগ করার পরে, আপনি ক্লাউড শেল টার্মিনাল দেখতে পাবেন:
এই ভার্চুয়াল মেশিনটি আপনার প্রয়োজনীয় সমস্ত ডেভেলপমেন্ট টুল দিয়ে লোড করা হয়েছে। এটি একটি ক্রমাগত 5GB হোম ডিরেক্টরি অফার করে এবং Google ক্লাউডে চলে, যা নেটওয়ার্ক কর্মক্ষমতা এবং প্রমাণীকরণকে ব্যাপকভাবে উন্নত করে। এই কোডল্যাবে আপনার সমস্ত কাজ একটি ব্রাউজার বা আপনার Chromebook দিয়ে করা যেতে পারে৷ একবার ক্লাউড শেলের সাথে সংযুক্ত হয়ে গেলে, আপনি দেখতে পাবেন যে আপনি ইতিমধ্যেই প্রমাণীকরণ করেছেন এবং প্রকল্পটি ইতিমধ্যেই আপনার প্রকল্প আইডিতে সেট করা আছে৷ - আপনি প্রমাণীকৃত কিনা তা নিশ্চিত করতে ক্লাউড শেলে নিম্নলিখিত কমান্ডটি চালান:
যদি আপনাকে একটি GCP API কল করার জন্য ক্লাউড শেলকে অনুমোদন করার জন্য অনুরোধ করা হয়, তাহলে অনুমোদন ক্লিক করুন।gcloud auth list
কমান্ড আউটপুট আপনার অ্যাকাউন্ট ডিফল্টরূপে নির্বাচিত না হলে, চালান:Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com>
$ gcloud config set account <ACCOUNT>
- আপনি সঠিক প্রকল্প নির্বাচন করেছেন তা নিশ্চিত করুন। ক্লাউড শেলে, চালান:
কমান্ড আউটপুটgcloud config list project
যদি সঠিক প্রকল্পটি ফেরত না দেওয়া হয়, আপনি এই কমান্ডের সাথে এটি সেট করতে পারেন:[core] project = <PROJECT_ID>
কমান্ড আউটপুটgcloud config set project <PROJECT_ID>
Updated property [core/project].
আপনি এই কোডল্যাবটি সম্পূর্ণ করার সাথে সাথে আপনি কমান্ড লাইন অপারেশন ব্যবহার করবেন এবং ফাইলগুলি সম্পাদনা করবেন। ফাইল সম্পাদনার জন্য, আপনি ক্লাউড শেল টুলবারের ডানদিকে ওপেন এডিটর ক্লিক করে ক্লাউড শেল-এর অন্তর্নির্মিত কোড এডিটর, ক্লাউড শেল সম্পাদকের সাথে কাজ করতে পারেন। ভিম এবং ইমাক্সের মতো জনপ্রিয় সম্পাদকরাও ক্লাউড শেল-এ উপলব্ধ।
3. ক্লাউড ফাংশন, ক্লাউড বিল্ড, এবং Google চ্যাট API সক্ষম করুন৷
ক্লাউড শেল থেকে, এই API এবং পরিষেবাগুলি সক্ষম করুন:
gcloud services enable \ cloudfunctions \ cloudbuild.googleapis.com \ chat.googleapis.com
এই অপারেশনটি সম্পূর্ণ হতে কয়েক মুহূর্ত সময় লাগতে পারে।
একবার সম্পন্ন হলে, এটির অনুরূপ একটি সাফল্যের বার্তা প্রদর্শিত হবে:
Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.
4. প্রাথমিক চ্যাট অ্যাপ তৈরি করুন
প্রকল্পটি শুরু করুন
শুরু করতে, আপনি একটি সাধারণ "হ্যালো ওয়ার্ল্ড" অ্যাপ তৈরি এবং স্থাপন করবেন। চ্যাট অ্যাপ হল ওয়েব পরিষেবা যা https অনুরোধে সাড়া দেয় এবং JSON পেলোড দিয়ে সাড়া দেয়। এই অ্যাপটির জন্য, আপনি Node.js এবং ক্লাউড ফাংশন ব্যবহার করবেন।
ক্লাউড শেল- এ, poll-app
নামে একটি নতুন ডিরেক্টরি তৈরি করুন এবং এটিতে নেভিগেট করুন:
mkdir ~/poll-app cd ~/poll-app
কোডল্যাবের জন্য অবশিষ্ট সমস্ত কাজ এবং আপনি যে ফাইলগুলি তৈরি করবেন তা এই ডিরেক্টরিতে থাকবে।
Node.js প্রকল্প শুরু করুন:
npm init
NPM প্রকল্প কনফিগারেশন সম্পর্কে বিভিন্ন প্রশ্ন জিজ্ঞাসা করে, যেমন নাম এবং সংস্করণ। প্রতিটি প্রশ্নের জন্য, ডিফল্ট মান গ্রহণ করতে ENTER
টিপুন। ডিফল্ট এন্ট্রি পয়েন্ট হল index.js
নামের একটি ফাইল, যা আমরা পরবর্তীতে তৈরি করব।
চ্যাট অ্যাপ ব্যাকএন্ড তৈরি করুন
অ্যাপ তৈরি শুরু করার সময়। নিম্নলিখিত বিষয়বস্তু সহ index.js
নামে একটি ফাইল তৈরি করুন:
/**
* App entry point.
*/
exports.app = async (req, res) => {
if (!(req.method === 'POST' && req.body)) {
res.status(400).send('')
}
const event = req.body;
let reply = {};
if (event.type === 'MESSAGE') {
reply = {
text: `Hello ${event.user.displayName}`
};
}
res.json(reply)
}
অ্যাপটি এখনও অনেক কিছু করবে না, কিন্তু ঠিক আছে। আপনি পরে আরও কার্যকারিতা যোগ করবেন।
অ্যাপটি স্থাপন করুন
"হ্যালো ওয়ার্ল্ড" অ্যাপটি স্থাপন করতে, আপনি ক্লাউড ফাংশন স্থাপন করবেন, Google ক্লাউড কনসোলে চ্যাট অ্যাপটি কনফিগার করবেন এবং স্থাপনা যাচাই করতে অ্যাপটিতে একটি পরীক্ষা বার্তা পাঠাবেন।
ক্লাউড ফাংশন স্থাপন করুন
"হ্যালো ওয়ার্ল্ড" অ্যাপের ক্লাউড ফাংশন স্থাপন করতে, নিম্নলিখিত কমান্ডটি প্রবেশ করান:
gcloud functions deploy app --trigger-http --security-level=secure-always --allow-unauthenticated --runtime nodejs14
শেষ হলে, আউটপুটটি এইরকম দেখতে হবে:
availableMemoryMb: 256
buildId: 993b2ca9-2719-40af-86e4-42c8e4563a4b
buildName: projects/595241540133/locations/us-central1/builds/993b2ca9-2719-40af-86e4-42c8e4563a4b
entryPoint: app
httpsTrigger:
securityLevel: SECURE_ALWAYS
url: https://us-central1-poll-app-codelab.cloudfunctions.net/app
ingressSettings: ALLOW_ALL
labels:
deployment-tool: cli-gcloud
name: projects/poll-app-codelab/locations/us-central1/functions/app
runtime: nodejs14
serviceAccountEmail: poll-app-codelab@appspot.gserviceaccount.com
sourceUploadUrl: https://storage.googleapis.com/gcf-upload-us-central1-66a01777-67f0-46d7-a941-079c24414822/94057943-2b7c-4b4c-9a21-bb3acffc84c6.zip
status: ACTIVE
timeout: 60s
updateTime: '2021-09-17T19:30:33.694Z'
versionId: '1'
httpsTrigger.url
প্রপার্টিতে নিয়োজিত ফাংশনের URL টি নোট করুন। আপনি পরবর্তী ধাপে এটি ব্যবহার করবেন।
অ্যাপটি কনফিগার করুন
অ্যাপটি কনফিগার করতে, ক্লাউড কনসোলে চ্যাট কনফিগারেশন পৃষ্ঠায় যান
- পরিষ্কার করুন এই চ্যাট অ্যাপটিকে ওয়ার্কস্পেস অ্যাড-অন হিসাবে তৈরি করুন এবং নিশ্চিত করতে নিষ্ক্রিয় ক্লিক করুন৷
- অ্যাপের নামে , "PollCodelab" লিখুন।
- Avatar URL- এ,
https://raw.githubusercontent.com/google/material-design-icons/master/png/social/poll/materialicons/24dp/2x/baseline_poll_black_24dp.png
লিখুন। - বর্ণনায় , "কোডল্যাবের জন্য পোল অ্যাপ" লিখুন।
- কার্যকারিতার অধীনে, 1:1 বার্তা গ্রহণ করুন এবং স্পেস এবং গ্রুপ কথোপকথনে যোগ দিন নির্বাচন করুন।
- সংযোগ সেটিংসের অধীনে, HTTP এন্ডপয়েন্ট URL নির্বাচন করুন এবং ক্লাউড ফাংশনের জন্য URLটি আটকান (শেষ বিভাগ থেকে
httpsTrigger.url
বৈশিষ্ট্য)। - অনুমতির অধীনে, আপনার ডোমেনে নির্দিষ্ট ব্যক্তি এবং গোষ্ঠী নির্বাচন করুন এবং আপনার ইমেল ঠিকানা লিখুন।
- সংরক্ষণ ক্লিক করুন.
অ্যাপটি এখন বার্তা দেওয়ার জন্য প্রস্তুত।
অ্যাপটি পরীক্ষা করুন
এগিয়ে যাওয়ার আগে, Google চ্যাটের একটি স্পেসে যোগ করে অ্যাপটি কাজ করছে কিনা তা পরীক্ষা করে দেখুন।
- গুগল চ্যাটে যান।
- চ্যাটের পাশে, +> অ্যাপস খুঁজুন এ ক্লিক করুন।
- অনুসন্ধানে "PollCodelab" লিখুন।
- চ্যাট এ ক্লিক করুন।
- অ্যাপটিতে বার্তা দিতে, "হ্যালো" টাইপ করুন এবং এন্টার টিপুন।
অ্যাপটিকে একটি সংক্ষিপ্ত হ্যালো বার্তার সাথে প্রতিক্রিয়া জানাতে হবে।
এখন যেখানে একটি মৌলিক কঙ্কাল রয়েছে, এটিকে আরও দরকারী কিছুতে পরিণত করার সময়!
5. পোল বৈশিষ্ট্যগুলি তৈরি করুন৷
অ্যাপটি কীভাবে কাজ করবে তার একটি দ্রুত ওভারভিউ
অ্যাপটি দুটি প্রধান অংশ নিয়ে গঠিত:
- একটি স্ল্যাশ কমান্ড যা পোল কনফিগার করার জন্য একটি ডায়ালগ প্রদর্শন করে।
- ভোট এবং ফলাফল দেখার জন্য একটি ইন্টারেক্টিভ কার্ড।
পোল কনফিগারেশন এবং ফলাফল সংরক্ষণ করার জন্য অ্যাপটির কিছু অবস্থারও প্রয়োজন। এটি ফায়ারস্টোর বা যেকোনো ডাটাবেসের সাথে করা যেতে পারে, বা স্টেট অ্যাপের বার্তাগুলিতে নিজেরাই সংরক্ষণ করা যেতে পারে। যেহেতু এই অ্যাপটি একটি দলের দ্রুত অনানুষ্ঠানিক ভোটের উদ্দেশ্যে, তাই অ্যাপের বার্তাগুলিতে রাজ্য সংরক্ষণ করা এই ব্যবহারের ক্ষেত্রে দুর্দান্ত কাজ করে।
অ্যাপের ডেটা মডেল (টাইপস্ক্রিপ্টে প্রকাশ করা হয়েছে):
interface Poll {
/* Question/topic of poll */
topic: string;
/** User that submitted the poll */
author: {
/** Unique resource name of user */
name: string;
/** Display name */
displayName: string;
};
/** Available choices to present to users */
choices: string[];
/** Map of user ids to the index of their selected choice */
votes: { [key: string]: number };
}
বিষয় বা প্রশ্ন এবং পছন্দের তালিকা ছাড়াও, রাষ্ট্র লেখকের আইডি এবং নাম এবং সেইসাথে রেকর্ড করা ভোটগুলি অন্তর্ভুক্ত করে। ব্যবহারকারীদের একাধিকবার ভোট দেওয়া থেকে বিরত রাখতে, ভোটগুলি তাদের নির্বাচিত পছন্দের সূচীতে ব্যবহারকারী আইডির মানচিত্র হিসাবে সংরক্ষণ করা হয়।
অবশ্যই, অনেকগুলি ভিন্ন পন্থা আছে কিন্তু এটি একটি স্থানের দ্রুত ভোট চালানোর জন্য একটি ভাল সূচনা বিন্দু প্রদান করে।
পোল কনফিগারেশন কমান্ড প্রয়োগ করুন
ব্যবহারকারীদের ভোট শুরু এবং কনফিগার করতে দিতে, একটি স্ল্যাশ কমান্ড সেট আপ করুন যা একটি ডায়ালগ খোলে। এটি একটি বহু-পদক্ষেপ প্রক্রিয়া:
- স্ল্যাশ কমান্ড নিবন্ধন করুন যা একটি পোল শুরু করে।
- একটি পোল সেট আপ করে এমন ডায়ালগ তৈরি করুন৷
- অ্যাপটিকে স্ল্যাশ কমান্ড চিনতে এবং পরিচালনা করতে দিন।
- ইন্টারেক্টিভ কার্ড তৈরি করুন যা পোলে ভোট দেওয়ার সুবিধা দেয়।
- কোডটি প্রয়োগ করুন যা অ্যাপটিকে পোল চালাতে দেয়।
- ক্লাউড ফাংশন পুনরায় স্থাপন করুন।
স্ল্যাশ কমান্ড নিবন্ধন করুন
একটি স্ল্যাশ কমান্ড নিবন্ধন করতে, কনসোলে চ্যাট কনফিগারেশন পৃষ্ঠায় ফিরে যান ( APIs & Services > Dashboard > Hangouts Chat API > Configuration )।
- স্ল্যাশ কমান্ডের অধীনে, একটি নতুন স্ল্যাশ কমান্ড যোগ করুন ক্লিক করুন।
- নামে , "/ পোল" লিখুন
- কমান্ড আইডিতে , "1" লিখুন
- বর্ণনায় , "একটি পোল শুরু করুন" লিখুন।
- একটি ডায়ালগ খোলে নির্বাচন করুন।
- সম্পন্ন ক্লিক করুন.
- সংরক্ষণ করুন ক্লিক করুন.
অ্যাপটি এখন /poll
কমান্ডকে স্বীকৃতি দেয় এবং এটি একটি ডায়ালগ খোলে। এর পরে, ডায়ালগ কনফিগার করা যাক।
একটি ডায়ালগ হিসাবে কনফিগারেশন ফর্ম তৈরি করুন
স্ল্যাশ কমান্ড ভোটের বিষয় এবং সম্ভাব্য পছন্দগুলি কনফিগার করার জন্য একটি ডায়ালগ খোলে। নিম্নলিখিত বিষয়বস্তু সহ config-form.js
নামে একটি নতুন ফাইল তৈরি করুন:
/** Upper bounds on number of choices to present. */
const MAX_NUM_OF_OPTIONS = 5;
/**
* Build widget with instructions on how to use form.
*
* @returns {object} card widget
*/
function helpText() {
return {
textParagraph: {
text: 'Enter the poll topic and up to 5 choices in the poll. Blank options will be omitted.',
},
};
}
/**
* Build the text input for a choice.
*
* @param {number} index - Index to identify the choice
* @param {string|undefined} value - Initial value to render (optional)
* @returns {object} card widget
*/
function optionInput(index, value) {
return {
textInput: {
label: `Option ${index + 1}`,
type: 'SINGLE_LINE',
name: `option${index}`,
value: value || '',
},
};
}
/**
* Build the text input for the poll topic.
*
* @param {string|undefined} topic - Initial value to render (optional)
* @returns {object} card widget
*/
function topicInput(topic) {
return {
textInput: {
label: 'Topic',
type: 'MULTIPLE_LINE',
name: 'topic',
value: topic || '',
},
};
}
/**
* Build the buttons/actions for the form.
*
* @returns {object} card widget
*/
function buttons() {
return {
buttonList: {
buttons: [
{
text: 'Submit',
onClick: {
action: {
function: 'start_poll',
},
},
},
],
},
};
}
/**
* Build the configuration form.
*
* @param {object} options - Initial state to render with form
* @param {string|undefined} options.topic - Topic of poll (optional)
* @param {string[]|undefined} options.choices - Text of choices to display to users (optional)
* @returns {object} card
*/
function buildConfigurationForm(options) {
const widgets = [];
widgets.push(helpText());
widgets.push(topicInput(options.topic));
for (let i = 0; i < MAX_NUM_OF_OPTIONS; ++i) {
const choice = options?.choices?.[i];
widgets.push(optionInput(i, choice));
}
widgets.push(buttons());
// Assemble the card
return {
sections: [
{
widgets,
},
],
};
}
exports.MAX_NUM_OF_OPTIONS = MAX_NUM_OF_OPTIONS;
exports.buildConfigurationForm = buildConfigurationForm;
এই কোড ডায়ালগ ফর্ম তৈরি করে যা ব্যবহারকারীকে পোল সেট আপ করতে দেয়। এটি একটি প্রশ্ন থাকতে পারে এমন সর্বাধিক সংখ্যক পছন্দের জন্য একটি ধ্রুবক রপ্তানি করে। UI মার্কআপটিকে স্টেটলেস ফাংশনে বিচ্ছিন্ন করার একটি ভাল অভ্যাস যা প্যারামিটার হিসাবে পাস করা যেকোনো স্টেটের সাথে। এটি পুনঃব্যবহারের সুবিধা দেয় এবং পরে এই কার্ডটি বিভিন্ন প্রসঙ্গে রেন্ডার করা হবে।
এই বাস্তবায়ন কার্ডটিকে ছোট একক বা উপাদানে বিভক্ত করে। প্রয়োজন না হলেও, কৌশলটি একটি সর্বোত্তম অনুশীলন কারণ এটি জটিল ইন্টারফেস তৈরি করার সময় আরও পাঠযোগ্য এবং রক্ষণাবেক্ষণযোগ্য হতে থাকে।
এটি তৈরি করা সম্পূর্ণ JSON এর একটি নমুনা দেখতে, এটি কার্ড বিল্ডার টুলে দেখুন।
স্ল্যাশ কমান্ডটি পরিচালনা করুন
অ্যাপে পাঠানো হলে স্ল্যাশ কমান্ড MESSAGE
ইভেন্ট হিসাবে উপস্থিত হয়। একটি MESSAGE
ইভেন্টের মাধ্যমে একটি স্ল্যাশ কমান্ডের উপস্থিতি পরীক্ষা করতে এবং একটি ডায়ালগের সাথে প্রতিক্রিয়া জানাতে index.js
আপডেট করুন৷ নিম্নলিখিত দিয়ে index.js
প্রতিস্থাপন করুন:
const { buildConfigurationForm, MAX_NUM_OF_OPTIONS } = require('./config-form');
/**
* App entry point.
*/
exports.app = async (req, res) => {
if (!(req.method === 'POST' && req.body)) {
res.status(400).send('')
}
const event = req.body;
let reply = {};
// Dispatch slash and action events
if (event.type === 'MESSAGE') {
const message = event.message;
if (message.slashCommand?.commandId === '1') {
reply = showConfigurationForm(event);
}
} else if (event.type === 'CARD_CLICKED') {
if (event.action?.actionMethodName === 'start_poll') {
reply = await startPoll(event);
}
}
res.json(reply);
}
/**
* Handles the slash command to display the config form.
*
* @param {object} event - chat event
* @returns {object} Response to send back to Chat
*/
function showConfigurationForm(event) {
// Seed the topic with any text after the slash command
const topic = event.message?.argumentText?.trim();
const dialog = buildConfigurationForm({
topic,
choices: [],
});
return {
actionResponse: {
type: 'DIALOG',
dialogAction: {
dialog: {
body: dialog,
},
},
},
};
}
/**
* Handle the custom start_poll action.
*
* @param {object} event - chat event
* @returns {object} Response to send back to Chat
*/
function startPoll(event) {
// Not fully implemented yet -- just close the dialog
return {
actionResponse: {
type: 'DIALOG',
dialogAction: {
actionStatus: {
statusCode: 'OK',
userFacingMessage: 'Poll started.',
},
},
},
}
}
অ্যাপটি এখন একটি ডায়ালগ প্রদর্শন করবে যখন /poll
কমান্ডটি চালু করা হবে। ক্লাউড শেল থেকে ক্লাউড ফাংশন পুনরায় প্রয়োগ করে মিথস্ক্রিয়া পরীক্ষা করুন।
gcloud functions deploy app --trigger-http --security-level=secure-always
ক্লাউড ফাংশন মোতায়েন করার পরে, স্ল্যাশ কমান্ড এবং ডায়ালগ পরীক্ষা করতে /poll
কমান্ড দিয়ে অ্যাপটিতে বার্তা পাঠান। ডায়ালগটি কাস্টম অ্যাকশন start_poll
সহ একটি CARD_CLICKED
ইভেন্ট পাঠায়। ইভেন্টটি আপডেট করা এন্ট্রি পয়েন্টে পরিচালনা করা হয় যেখানে এটি startPoll
পদ্ধতিকে কল করে। আপাতত, ডায়ালগ বন্ধ করার জন্য startPoll
পদ্ধতিটি স্টাব করা হয়েছে। পরবর্তী বিভাগে, আপনি ভোট প্রদানের কার্যকারিতা বাস্তবায়ন করবেন এবং সমস্ত অংশ একসাথে সংযুক্ত করবেন।
ভোট কার্ড বাস্তবায়ন করুন
অ্যাপের ভোটদানের অংশ বাস্তবায়ন করতে, ইন্টারেক্টিভ কার্ডটি সংজ্ঞায়িত করে শুরু করুন যা লোকেদের ভোট দেওয়ার জন্য একটি ইন্টারফেস প্রদান করে।
ভোট ইন্টারফেস বাস্তবায়ন
নিম্নলিখিত বিষয়বস্তু সহ vote-card.js
নামে একটি ফাইল তৈরি করুন:
/**
* Creates a small progress bar to show percent of votes for an option. Since
* width is limited, the percentage is scaled to 20 steps (5% increments).
*
* @param {number} voteCount - Number of votes for this option
* @param {number} totalVotes - Total votes cast in the poll
* @returns {string} Text snippet with bar and vote totals
*/
function progressBarText(voteCount, totalVotes) {
if (voteCount === 0 || totalVotes === 0) {
return '';
}
// For progress bar, calculate share of votes and scale it
const percentage = (voteCount * 100) / totalVotes;
const progress = Math.round((percentage / 100) * 20);
return '▀'.repeat(progress);
}
/**
* Builds a line in the card for a single choice, including
* the current totals and voting action.
*
* @param {number} index - Index to identify the choice
* @param {string|undefined} value - Text of the choice
* @param {number} voteCount - Current number of votes cast for this item
* @param {number} totalVotes - Total votes cast in poll
* @param {string} state - Serialized state to send in events
* @returns {object} card widget
*/
function choice(index, text, voteCount, totalVotes, state) {
const progressBar = progressBarText(voteCount, totalVotes);
return {
keyValue: {
bottomLabel: `${progressBar} ${voteCount}`,
content: text,
button: {
textButton: {
text: 'vote',
onClick: {
action: {
actionMethodName: 'vote',
parameters: [
{
key: 'state',
value: state,
},
{
key: 'index',
value: index.toString(10),
},
],
},
},
},
},
},
};
}
/**
* Builds the card header including the question and author details.
*
* @param {string} topic - Topic of the poll
* @param {string} author - Display name of user that created the poll
* @returns {object} card widget
*/
function header(topic, author) {
return {
title: topic,
subtitle: `Posted by ${author}`,
imageUrl:
'https://raw.githubusercontent.com/google/material-design-icons/master/png/social/poll/materialicons/24dp/2x/baseline_poll_black_24dp.png',
imageStyle: 'AVATAR',
};
}
/**
* Builds the configuration form.
*
* @param {object} poll - Current state of poll
* @param {object} poll.author - User that submitted the poll
* @param {string} poll.topic - Topic of poll
* @param {string[]} poll.choices - Text of choices to display to users
* @param {object} poll.votes - Map of cast votes keyed by user ids
* @returns {object} card
*/
function buildVoteCard(poll) {
const widgets = [];
const state = JSON.stringify(poll);
const totalVotes = Object.keys(poll.votes).length;
for (let i = 0; i < poll.choices.length; ++i) {
// Count votes for this choice
const votes = Object.values(poll.votes).reduce((sum, vote) => {
if (vote === i) {
return sum + 1;
}
return sum;
}, 0);
widgets.push(choice(i, poll.choices[i], votes, totalVotes, state));
}
return {
header: header(poll.topic, poll.author.displayName),
sections: [
{
widgets,
},
],
};
}
exports.buildVoteCard = buildVoteCard;
বাস্তবায়নটি ডায়ালগের সাথে নেওয়া পদ্ধতির অনুরূপ, যদিও ইন্টারেক্টিভ কার্ডের জন্য মার্কআপ ডায়ালগের চেয়ে কিছুটা আলাদা। আগের মতো, আপনি কার্ড বিল্ডার টুলে জেনারেট করা JSON-এর নমুনা দেখতে পারেন।
ভোট কার্যক্রম বাস্তবায়ন করুন
ভোটিং কার্ডে প্রতিটি পছন্দের জন্য একটি বোতাম রয়েছে। সেই পছন্দের সূচী, ভোটের ক্রমিক অবস্থা সহ, বোতামের সাথে সংযুক্ত থাকে। অ্যাপটি প্যারামিটার হিসাবে বোতামের সাথে সংযুক্ত যেকোনো ডেটা সহ অ্যাকশন vote
সহ একটি CARD_CLICKED
পায়।
এর সাথে index.js
আপডেট করুন:
const { buildConfigurationForm, MAX_NUM_OF_OPTIONS } = require('./config-form');
const { buildVoteCard } = require('./vote-card');
/**
* App entry point.
*/
exports.app = async (req, res) => {
if (!(req.method === 'POST' && req.body)) {
res.status(400).send('')
}
const event = req.body;
let reply = {};
// Dispatch slash and action events
if (event.type === 'MESSAGE') {
const message = event.message;
if (message.slashCommand?.commandId === '1') {
reply = showConfigurationForm(event);
}
} else if (event.type === 'CARD_CLICKED') {
if (event.action?.actionMethodName === 'start_poll') {
reply = await startPoll(event);
} else if (event.action?.actionMethodName === 'vote') {
reply = recordVote(event);
}
}
res.json(reply);
}
/**
* Handles the slash command to display the config form.
*
* @param {object} event - chat event
* @returns {object} Response to send back to Chat
*/
function showConfigurationForm(event) {
// Seed the topic with any text after the slash command
const topic = event.message?.argumentText?.trim();
const dialog = buildConfigurationForm({
topic,
choices: [],
});
return {
actionResponse: {
type: 'DIALOG',
dialogAction: {
dialog: {
body: dialog,
},
},
},
};
}
/**
* Handle the custom start_poll action.
*
* @param {object} event - chat event
* @returns {object} Response to send back to Chat
*/
function startPoll(event) {
// Not fully implemented yet -- just close the dialog
return {
actionResponse: {
type: 'DIALOG',
dialogAction: {
actionStatus: {
statusCode: 'OK',
userFacingMessage: 'Poll started.',
},
},
},
}
}
/**
* Handle the custom vote action. Updates the state to record
* the user's vote then rerenders the card.
*
* @param {object} event - chat event
* @returns {object} Response to send back to Chat
*/
function recordVote(event) {
const parameters = event.common?.parameters;
const choice = parseInt(parameters['index']);
const userId = event.user.name;
const state = JSON.parse(parameters['state']);
// Add or update the user's selected option
state.votes[userId] = choice;
const card = buildVoteCard(state);
return {
thread: event.message.thread,
actionResponse: {
type: 'UPDATE_MESSAGE',
},
cards: [card],
}
}
recordVote
পদ্ধতিটি সঞ্চিত অবস্থাকে পার্স করে এবং ব্যবহারকারীর ভোটের সাথে আপডেট করে, তারপর কার্ডটি পুনরায় রেন্ডার করে। ভোটের ফলাফল ক্রমিক করা হয় এবং কার্ডের সাথে সংরক্ষণ করা হয় যতবার আপডেট করা হয়।
টুকরা সংযুক্ত করুন
অ্যাপটি প্রায় শেষ। ভোটের সাথে স্ল্যাশ কমান্ড প্রয়োগ করা হলে, শুধুমাত্র startPoll
পদ্ধতিটি শেষ করা বাকি।
কিন্তু, একটি ধরা আছে.
যখন পোল কনফিগারেশন জমা দেওয়া হয়, অ্যাপটিকে দুটি ক্রিয়া সম্পাদন করতে হবে:
- ডায়ালগ বন্ধ করুন।
- ভোটিং কার্ড সহ স্পেসে একটি নতুন বার্তা পোস্ট করুন।
দুর্ভাগ্যবশত, HTTP অনুরোধের সরাসরি উত্তর শুধুমাত্র একটি করতে পারে, এবং এটি অবশ্যই প্রথম হতে হবে। ভোট কার্ড পোস্ট করতে, অ্যাসিঙ্ক্রোনাসভাবে একটি নতুন বার্তা তৈরি করতে অ্যাপটিকে চ্যাট API ব্যবহার করতে হবে।
ক্লায়েন্ট লাইব্রেরি যোগ করুন
Node.js-এর জন্য Google API ক্লায়েন্ট অন্তর্ভুক্ত করতে অ্যাপের নির্ভরতা আপডেট করতে নিম্নলিখিত কমান্ডটি চালান।
npm install --save googleapis
ভোট শুরু করুন
নীচের চূড়ান্ত সংস্করণে index.js
আপডেট করুন:
const { buildConfigurationForm, MAX_NUM_OF_OPTIONS } = require('./config-form');
const { buildVoteCard } = require('./vote-card');
const {google} = require('googleapis');
/**
* App entry point.
*/
exports.app = async (req, res) => {
if (!(req.method === 'POST' && req.body)) {
res.status(400).send('')
}
const event = req.body;
let reply = {};
// Dispatch slash and action events
if (event.type === 'MESSAGE') {
const message = event.message;
if (message.slashCommand?.commandId === '1') {
reply = showConfigurationForm(event);
}
} else if (event.type === 'CARD_CLICKED') {
if (event.action?.actionMethodName === 'start_poll') {
reply = await startPoll(event);
} else if (event.action?.actionMethodName === 'vote') {
reply = recordVote(event);
}
}
res.json(reply);
}
/**
* Handles the slash command to display the config form.
*
* @param {object} event - chat event
* @returns {object} Response to send back to Chat
*/
function showConfigurationForm(event) {
// Seed the topic with any text after the slash command
const topic = event.message?.argumentText?.trim();
const dialog = buildConfigurationForm({
topic,
choices: [],
});
return {
actionResponse: {
type: 'DIALOG',
dialogAction: {
dialog: {
body: dialog,
},
},
},
};
}
/**
* Handle the custom start_poll action.
*
* @param {object} event - chat event
* @returns {object} Response to send back to Chat
*/
async function startPoll(event) {
// Get the form values
const formValues = event.common?.formInputs;
const topic = formValues?.['topic']?.stringInputs.value[0]?.trim();
const choices = [];
for (let i = 0; i < MAX_NUM_OF_OPTIONS; ++i) {
const choice = formValues?.[`option${i}`]?.stringInputs.value[0]?.trim();
if (choice) {
choices.push(choice);
}
}
if (!topic || choices.length === 0) {
// Incomplete form submitted, rerender
const dialog = buildConfigurationForm({
topic,
choices,
});
return {
actionResponse: {
type: 'DIALOG',
dialogAction: {
dialog: {
body: dialog,
},
},
},
};
}
// Valid configuration, build the voting card to display
// in the space
const pollCard = buildVoteCard({
topic: topic,
author: event.user,
choices: choices,
votes: {},
});
const message = {
cards: [pollCard],
};
const request = {
parent: event.space.name,
requestBody: message,
};
// Use default credentials (service account)
const credentials = new google.auth.GoogleAuth({
scopes: ['https://www.googleapis.com/auth/chat.bot'],
});
const chatApi = google.chat({
version: 'v1',
auth: credentials,
});
await chatApi.spaces.messages.create(request);
// Close dialog
return {
actionResponse: {
type: 'DIALOG',
dialogAction: {
actionStatus: {
statusCode: 'OK',
userFacingMessage: 'Poll started.',
},
},
},
};
}
/**
* Handle the custom vote action. Updates the state to record
* the user's vote then rerenders the card.
*
* @param {object} event - chat event
* @returns {object} Response to send back to Chat
*/
function recordVote(event) {
const parameters = event.common?.parameters;
const choice = parseInt(parameters['index']);
const userId = event.user.name;
const state = JSON.parse(parameters['state']);
// Add or update the user's selected option
state.votes[userId] = choice;
const card = buildVoteCard(state);
return {
thread: event.message.thread,
actionResponse: {
type: 'UPDATE_MESSAGE',
},
cards: [card],
}
}
ফাংশন পুনরায় স্থাপন করুন:
gcloud functions deploy app --trigger-http --security-level=secure-always
আপনি এখন সম্পূর্ণরূপে অ্যাপ্লিকেশন ব্যায়াম করতে সক্ষম হওয়া উচিত. একটি প্রশ্ন এবং কয়েকটি পছন্দ প্রদান করার জন্য /poll
কমান্ডটি ব্যবহার করার চেষ্টা করুন। জমা দেওয়ার পরে, পোল কার্ড প্রদর্শিত হবে।
আপনার ভোট দিন এবং দেখুন কি হয়.
অবশ্যই নিজেকে পোলিং করা এতটা দরকারী নয়, তাই কিছু বন্ধু বা সহকর্মীদের আমন্ত্রণ জানান এটি চেষ্টা করার জন্য!
6. অভিনন্দন
অভিনন্দন! আপনি ক্লাউড ফাংশন ব্যবহার করে সফলভাবে একটি Google Chat অ্যাপ তৈরি ও স্থাপন করেছেন। যদিও কোডল্যাব একটি অ্যাপ তৈরির জন্য অনেকগুলি মূল ধারণাগুলিকে কভার করে, সেখানে আরও অনেক কিছু অন্বেষণ করার আছে৷ নীচের সংস্থানগুলি দেখুন এবং অতিরিক্ত চার্জ এড়াতে আপনার প্রকল্পটি পরিষ্কার করতে ভুলবেন না৷
অতিরিক্ত কার্যক্রম
আপনি যদি চ্যাট প্ল্যাটফর্ম এবং এই অ্যাপটি আরও গভীরভাবে অন্বেষণ করতে চান তবে এখানে কয়েকটি জিনিস রয়েছে যা আপনি নিজে চেষ্টা করতে পারেন:
- আপনি যখন অ্যাপটি উল্লেখ করেন তখন কী হয়? আচরণ উন্নত করতে অ্যাপটি আপডেট করার চেষ্টা করুন।
- কার্ডে পোল স্টেট সিরিয়ালাইজ করা ছোট জায়গার জন্য ঠিক আছে, কিন্তু এর সীমা আছে। একটি ভাল বিকল্পে স্যুইচ করার চেষ্টা করুন।
- যদি লেখক পোল সম্পাদনা করতে চান, বা নতুন ভোট নেওয়া বন্ধ করতে চান? আপনি কিভাবে এই বৈশিষ্ট্যগুলি বাস্তবায়ন করবেন?
- অ্যাপের এন্ডপয়েন্ট এখনও সুরক্ষিত নয়। Google Chat থেকে অনুরোধ আসছে কিনা তা নিশ্চিত করতে কিছু যাচাইকরণ যোগ করার চেষ্টা করুন।
এগুলি অ্যাপটিকে উন্নত করার কয়েকটি ভিন্ন উপায়। মজা করুন এবং আপনার কল্পনা ব্যবহার করুন!
পরিষ্কার করুন
এই টিউটোরিয়ালে ব্যবহৃত সংস্থানগুলির জন্য আপনার Google ক্লাউড প্ল্যাটফর্ম অ্যাকাউন্টে চার্জ এড়াতে:
- ক্লাউড কনসোলে, সম্পদ পরিচালনা পৃষ্ঠাতে যান। উপরের-বাম কোণায় ক্লিক করুন, মেনুতে ক্লিক করুন
> আইএএম এবং অ্যাডমিন > সম্পদ পরিচালনা করুন ।
- প্রকল্প তালিকায়, আপনার প্রকল্প নির্বাচন করুন তারপর মুছুন ক্লিক করুন।
- ডায়ালগে, প্রকল্প আইডি টাইপ করুন এবং তারপরে প্রকল্পটি মুছে ফেলতে শাট ডাউন ক্লিক করুন।
আরও জানুন
চ্যাট অ্যাপ ডেভেলপ করার বিষয়ে আরও তথ্যের জন্য, দেখুন:
Google ক্লাউড কনসোলে বিকাশ সম্পর্কে আরও তথ্যের জন্য, দেখুন: