Google App script - Telegram Bot - Inline Keyboard callback_query - google-apps-script

This here is my function that hears for anything incoming from Telegram. It does work well with any message and files or whatever but it doesn't work when i press a but of an inline_keyboard, Why?
How can i create a function that hears for a inline_keyboard button pressed?
function doPost(e) {
var data = JSON.parse(e.postData.contents);
sendText('personal_chat_id', JSON.stringify(data));
}
In case you need it here under is my function that can send a message with an inline_keyboard.
function lol(){
var keyboard ={
inline_keyboard: [
[
{
text: "A",
callback_data: 123
},
{
text: "B",
callback_data: 234
}
],
[
{
text: "C",
callback_data: 345
},
{
text: "D",
callback_data: 456
}
]
]
}
sendText('personal_chat_id', "lol", keyboard)
}
function sendText(chatId,text,keyBoard){
keyBoard = keyBoard || 0;
if(keyBoard.inline_keyboard || keyBoard.keyboard){
var data = {
method: "post",
payload: {
method: "sendMessage",
chat_id: String(chatId),
text: text,
parse_mode: "HTML",
reply_markup: JSON.stringify(keyBoard)
}
}
}
var response = UrlFetchApp.fetch('https://api.telegram.org/bot' + token + '/', data);
return response.getContentText()
}

You need to do it inside the doPost(e) function. Take the "e" parameter and verify what kind of type it is. If it is "contents.callback_query" is coming from the inline keyboard response and if it is "contents.message" it's text typed by the user.
And dont forget declare sendText() and sendKeyboard() functions.
function doPost(e) {
var contents = JSON.parse(e.postData.contents);
var keyboard = {
"inline_keyboard": [
[{
"text": "Players",
"callback_data": "player"
}],
[{
"text": "Match",
"callback_data": "match"
}],
[{
"text": "Results",
"callback_data": "result"
}]
]}
if (contents.callback_query) {
var id = contents.callback_query.message.chat.id;
var text = contents.callback_query.data;
switch (text) {
case 'Player':
var answer = 'Ingresa tu nombre y apellido';
sendText(id, answer);
break;
case 'match':
var answer = 'Ingresá tu nombre y apellido';
sendText(id, answer);
break;
case 'result':
var keyboard = {
'inline_keyboard': [
[{
'text': 'Youtube',
'url': 'https://youtube.com'
},{
'text': 'Google',
'url': 'https://google.com'
}]
]
};
sendTextWithButtons(id, 'Algunos enlaces', JSON.stringify(keyboard));
break;
default:
var answer = 'Default answer';
sendText(id, answer);
break;
}
var chat_id = contents.callback_query.from.id;
var user = contents.callback_query.message.chat.first_name;
var cb_data = contents.callback_query.data;
sendText(chat_id, CariDataDariIDSheet(cb_data));
}else if (contents.message) {
var chat_id = contents.message.from.id;
var user = contents.message.chat.first_name;
var answer = "your answer";
sendKeyboard(chat_id, answer, keyboard);
}
}

Related

App script once a week asking for authorization

I did a script (I'm not a programer) and I'm running to get a csv from metabase question. The only problem is because once a week as asking me to authorize again.
It shows:
"Authorisation required" "A script attached to this document needs your permission to run."
image step 02
image step 03
image step 04
What can I do to authorize forever?
I need to have the authorization forever. Not needed to authorize once a week because I'm running on time-base and automated. The code is below.
I have two files Code.gs and Code2.gs - on the first one I have another code.
function onInstall() {
onOpen();
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Import Question & Send Email')
.addItem('Import Question', 'importQuestion')
.addItem('Send Report by e-mail', 'sendReport')
.addToUi();
}
function importQuestion() {
var status = getQuestionAsCSV(metabaseQuestionNum, true);
var scriptProp = PropertiesService.getScriptProperties();
var metabaseQuestionNum = scriptProp.getProperty('QUESTION_ID');
var log = {
'user': Session.getActiveUser().getEmail(),
'function': 'importQuestion',
'questionNumber': metabaseQuestionNum,
'status': status
};
if (log.status === true) {
console.log(log);
} else {
console.error(log);
}
}
function getSheetNumbers() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var questionNumbers = [];
for (var i in sheets) {
var sheetName = sheets[i].getName();
if (sheetName.indexOf('(metabase/') > -1) {
var questionMatch = sheetName.match('\(metabase\/[0-9]+\)');
if (questionMatch !== null) {
var questionNumber = questionMatch[0].match('[0-9]+')[0];
if (!isNaN(questionNumber) && questionNumber !== '') {
questionNumbers.push({
'questionNumber': questionNumber,
'sheetName': sheetName
});
}
}
}
}
return questionNumbers;
}
function getToken(baseUrl, username, password) {
var sessionUrl = baseUrl + "api/session";
var options = {
"method": "post",
"headers": {
"Content-Type": "application/json"
},
"payload": JSON.stringify({
username: username,
password: password
})
};
var response;
try {
response = UrlFetchApp.fetch(sessionUrl, options);
} catch (e) {
throw (e);
}
var token = JSON.parse(response).id;
return token;
}
function getQuestionAndFillSheet(baseUrl, token, metabaseQuestionNum, sheetName) {
var questionUrl = baseUrl + "api/card/" + metabaseQuestionNum + "/query/csv";
var options = {
"method": "post",
"headers": {
"Content-Type": "application/json",
"X-Metabase-Session": token
},
"muteHttpExceptions": true
};
var response;
try {
response = UrlFetchApp.fetch(questionUrl, options);
} catch (e) {
return {
'success': false,
'error': e
};
}
var statusCode = response.getResponseCode();
if (statusCode == 200 || statusCode == 202) {
var values = Utilities.parseCsv(response.getContentText());
try {
fillSheet(values, sheetName);
return {
'success': true
};
} catch (e) {
return {
'success': false,
'error': e
};
}
} else if (statusCode == 401) {
var scriptProp = PropertiesService.getScriptProperties();
var username = scriptProp.getProperty('USERNAME');
var password = scriptProp.getProperty('PASSWORD');
var token = getToken(baseUrl, username, password);
scriptProp.setProperty('TOKEN', token);
var e = "Error: Could not retrieve question. Metabase says: '" + response.getContentText() + "'. Please try again in a few minutes.";
return {
'success': false,
'error': e
};
} else {
var e = "Error: Could not retrieve question. Metabase says: '" + response.getContentText() + "'. Please try again later.";
return {
'success': false,
'error': e
};
}
}
function fillSheet(values, sheetName) {
var colLetters = ["N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BK", "BL", "BM", "BN", "BO", "BP", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ", "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CI", "CJ", "CK", "CL", "CM", "CN", "CO", "CP", "CQ", "CR", "CS", "CT", "CU", "CV", "CW", "CX", "CY", "CZ", "DA", "DB", "DC", "DD", "DE", "DF", "DG", "DH", "DI", "DJ", "DK", "DL", "DM", "DN", "DO", "DP", "DQ", "DR", "DS", "DT", "DU", "DV", "DW", "DX", "DY", "DZ", "EA", "EB", "EC", "ED", "EE", "EF", "EG", "EH", "EI", "EJ", "EK", "EL", "EM", "EN", "EO", "EP", "EQ", "ER", "ES", "ET", "EU", "EV", "EW", "EX", "EY", "EZ", "FA", "FB", "FC", "FD", "FE", "FF", "FG", "FH", "FI", "FJ", "FK", "FL", "FM", "FN", "FO", "FP", "FQ", "FR", "FS", "FT", "FU", "FV", "FW", "FX", "FY", "FZ", "GA", "GB", "GC", "GD", "GE", "GF", "GG", "GH", "GI", "GJ", "GK", "GL", "GM", "GN", "GO", "GP", "GQ", "GR", "GS", "GT", "GU", "GV", "GW", "GX", "GY", "GZ", "HA", "HB", "HC", "HD", "HE", "HF", "HG", "HH", "HI", "HJ", "HK", "HL", "HM", "HN", "HO", "HP", "HQ", "HR", "HS", "HT", "HU", "HV", "HW", "HX", "HY", "HZ", "IA", "IB", "IC", "ID", "IE", "IF", "IG", "IH", "II", "IJ", "IK", "IL", "IM", "IN", "IO", "IP", "IQ", "IR", "IS", "IT", "IU", "IV", "IW", "IX", "IY", "IZ", "JA", "JB", "JC", "JD", "JE", "JF", "JG", "JH", "JI", "JJ", "JK", "JL", "JM", "JN", "JO", "JP", "JQ", "JR", "JS", "JT", "JU", "JV", "JW", "JX", "JY", "JZ"];
var sheet;
if (sheetName == false) {
sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
} else {
sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('AUTO-productivity');
}
var range = sheet.getRange(1,14,1000,4);
range.clear({contentsOnly: true});
var rows = values;
var header = rows[0];
var minCol = colLetters[0];
var maxCol = colLetters[header.length - 1];
var minRow = 1;
var maxRow = rows.length;
var range = sheet.getRange(minCol + minRow + ":" + maxCol + maxRow);
range.setValues(rows);
}
function getQuestionAsCSV(metabaseQuestionNum, sheetName) {
var scriptProp = PropertiesService.getScriptProperties();
var baseUrl = scriptProp.getProperty('BASE_URL');
var username = scriptProp.getProperty('USERNAME');
var password = scriptProp.getProperty('PASSWORD');
var token = scriptProp.getProperty('TOKEN');
var metabaseQuestionNum = scriptProp.getProperty('QUESTION_ID');
if (!token) {
token = getToken(baseUrl, username, password);
scriptProp.setProperty('TOKEN', token);
}
status = getQuestionAndFillSheet(baseUrl, token, metabaseQuestionNum, sheetName);
return status;
}
Maybe you could try to add scopes in manifest file
In project file, open Setup, and check display manifest file "appsscript.json", and then open it.
Add:
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/script.send_mail",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/gmail.modify",
]
Reference :
Scopes
List of scopes

Google chat app is not responding for image attachment

I am trying to save attachment uploaded by google chat app.
I am handling two cases if user messages anything to google chat app, it will pop up a card with widgets which is perfectly fine but I am handling if user uploads attachment it will save into google drive but the code is not working. Can someone please help?
I am new in coding.
function getByteStream(dataRef) {
var blob = "";
var driveFileName = "";
var url = "https://chat.googleapis.com/v1/media/"+ dataRef +"?alt=media"
var service = getOAuth2Service();
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + service.getAccessToken(),
},
'muteHttpExceptions': true,
});
if(response.getResponseCode() != 200){
return "Failed to get file content with error code: " + response.getResponseCode();
}
blob = response.getBlob();
driveFileName = DriveApp.createFile(blob);
return "The uploaded contents have been saved in a Google Drive file: "+ driveFileName;
}
function onMessage(event) {
if (event.message.attachment) {
var attachmentName = event.message.attachment[0].name;
var attachment = getByteStream(attachmentName);
console.log(attachment);
} else {
return {
"cards_v2": [{
"card_id": "addContact",
"card": {
"header": {
"title": "Hello" +" " + event.user.displayName + "!",
"subtitle": "Log your feedback!",
"imageUrl": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
"imageType": "CIRCLE"
},
"sections": [
{
"widgets": [
{
"buttonList": {
"buttons": [
{
"text": "Start here",
"onClick": {
"action": {
"function": "openDialog",
"interaction": "OPEN_DIALOG"
}
}
}
]
},
"horizontalAlignment": "CENTER"
}
]
}
]
}
}]
};
}
}

Send variable value in a webhook

I am trying to send a variable value pulled from a spreadsheet in a webhook, my issue is that i am not being able to pass the variable value in the "data variable", when i only send pure text, everything works fine but the variable value is not arriving, as it simple as it may sound, can anyone guide me on this matter? Thanks in advance.
function message (){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ws = ss.getSheetByName("Backlog Report");
var backlogValue = ws.getRange("U7").getValue();
var totalCases = ws.getRange("Z7").getValue();
console.log(backlogValue);
var data = {
text: "Backlog: " + backlogValue
};
var payload = JSON.stringify(data);
var options = {
method: "POST",
contentType: "application/json; charset=UTF-8",
payload: payload,
muteHttpExceptions: true
};
var webhook = 'https://chat.googleapis.com/v1/spaces/XXXX/messages?key=XXX';
var response = UrlFetchApp.fetch(webhook, options);
Logger.log(response.getContentText());
}
I was stuck with webhooks as well... i can't tell you exactly why the following works for me, but if it helps you solve your problem, then here you go with my function. I've used it to send google sheets data to one of my Discord Channels with a embed format.
I think the relevant part of this is, to get the value of a field
var docName = sheets.getRange('B2').getValue();
Full Function:
//Discord webhook Aktiv-Recruitment
function postMessageToDiscord() {
var sheets = SpreadsheetApp.getActiveSpreadsheet();
var docName = sheets.getRange('B2').getValue();
var docRealm = sheets.getRange('C2').getValue();
var docClass = sheets.getRange('D2').getValue();
var docBtag = sheets.getRange('J2').getValue();
var docProg = sheets.getRange('I2').getValue();
var docDate = sheets.getRange('K2').getValue();
var discordUrl = "YOUR_WEBHOOK_URL";
`changed to var payload = {content:message} and received the new error`
var payload = JSON.stringify({
"embeds": [{
"author":{
"name": docClass + " hinzugefügt!",
},
"title": docBtag,
"color": 15374745,
"url" : "SOME_LINK",
"fields": [
{
"name": "Name",
"value": docName,
"inline": true
},
{
"name": "Realm",
"value": docRealm,
"inline": true
},
{
"name": "Progress",
"value": docProg
}
],
"footer": {
"text": docDate
}
}]
});
var params = {
method: "POST",
payload: payload,
muteHttpExceptions : true,
contentType: "application/json"
};
var response = UrlFetchApp.fetch(discordUrl, params);
Logger.log(response.getContentText());
}

Using URFetchApp with Google Forms API returns 400 ccode error

I'm trying to use the new Google Forms API to add an image to an existing Google form. At the moment I'm just trying to change the image Alt Text. I haven't been able to get it to work. I keep getting a 400 error. I'm hooping someone can point out what I'm doing wrong.
TIA for any help
This is the code:
function callFormsAPI() {
Logger.log('Calling the Forms API!');
var formId = "1oxBZrRG6UEcrLSXrT9P9hcqgkvE12UQDYUOAYyg3eeA"
// Get OAuth Token
var OAuthToken = ScriptApp.getOAuthToken();
Logger.log('OAuth token is: ' + OAuthToken);
var path = "https://forms.googleapis.com/v1beta/forms/"
var formsAPIUrl = path+formId+':batchUpdate'
Logger.log('formsAPIUrl is: ' + formsAPIUrl);
var body = tempAPI()
var options = {
'headers': {
Authorization: 'Bearer ' + OAuthToken,
Accept: 'application/json'
},
muteHttpExceptions: true,
'method': 'post',
'payload' : JSON.stringify(body)
// 'payload' : body
};
var response = UrlFetchApp.fetch(formsAPIUrl, options);
Logger.log('Response from forms.responses was: ' + response);
var text = response.getContentText()
console.log(text)
}
function tempAPI(){
var itemId = "2005660890"
var imageString = 'https://images.unsplash.com/photo-1552519507-da3b142c6e3d';
var request = {
"requests": [
{
"updateItem": {
"item": {
"itemId": itemId,
"questionItem": {
"image": {
"altText": 'this is a car',
// "sourceUri": imageString
}
}
},
"updateMask": "altText"
// "updateMask": "item/questionItem/image/sourceUri"
} //end of update item
}
]
}
return request
}
This is the response I'm getting
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"{\"requests\":[{\"updateItem\":{\"item\":{\"itemId\":\"2005660890\",\"questionItem\":{\"image\":{\"altText\":\"this is a car\"}}},\"updateMask\":\"altText\"}}]}\": Cannot bind query parameter. Field '{\"requests\":[{\"updateItem\":{\"item\":{\"itemId\":\"2005660890\",\"questionItem\":{\"image\":{\"altText\":\"this is a car\"}}},\"updateMask\":\"altText\"}}]}' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"{\"requests\":[{\"updateItem\":{\"item\":{\"itemId\":\"2005660890\",\"questionItem\":{\"image\":{\"altText\":\"this is a car\"}}},\"updateMask\":\"altText\"}}]}\": Cannot bind query parameter. Field '{\"requests\":[{\"updateItem\":{\"item\":{\"itemId\":\"2005660890\",\"questionItem\":{\"image\":{\"altText\":\"this is a car\"}}},\"updateMask\":\"altText\"}}]}' could not be found in request message."
}
]
}
]
}
}

Google form notification script

The notification script give title and value, and I am trying to get value only without title
Google Form script
Method1
var POST_URL = "hidden url";
function onSubmit(e) {
var response = e.response.getItemResponses();
var items = [];
for (var i = 0; i < response.length ; i++) {
var question = response[i].getItem().getTitle();
var answer = response[i].getResponse();
var parts = answer.match(/[\s\S]{1,1024}/g) || [];
if (answer == "") {continue;}
for (var j = 0; j< parts.length; j++) {
if (j == 0) {
items.push({"name": question, "value": parts[j], "inline": true});
} else {
items.push({"name": question.concat(" (cont.)"), "value": parts[j], "inline": true});
}
}
}
var options = {
"method" : "post",
"payload": JSON.stringify({
"embeds": [
{
"title":"New request",
"fields":items,
}
]
}
)
};
UrlFetchApp.fetch(POST_URL, options);
};
Method2 added
function onFormSubmit(e) {
var fields = [];
for (i = 0; i < e.response.getItemResponses().length; i++) {
var response = e.response.getItemResponses()[i];
fields.push({
"name": response.getItem().getTitle(),
"value": JSON.stringify(response.getResponse()),
"inline": false
});
}
var data = {
"embeds": [{
"title": "**Test Rep** — " + (e.source.getTitle() != null && e.source.getTitle().length > 0 ? e.source.getTitle() : "Untitled Form"),
"type": "rich",
"fields": fields,
}]
};
var options = {
method: "post",
payload: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
muteHttpExceptions: true,
};
Logger.log("Attempting to send:");
Logger.log(JSON.stringify(data));
var response = UrlFetchApp.fetch("Hidden URL", options);
Logger.log(response.getContentText());
};
The method2 do same job as method1 but i hope someone can help to workaround
I expected to get notification with form title + the value of two fields without question title.
The problem
A form has the title "New request" and has two questions.
The notification should have the form title "New request" and the answers to the questions but not the questions themselves.
A solution
Try these steps:
(1) Remove or comment out
var question = response[i].getItem().getTitle();
(2) Change this
items.push({"name": question, "value": parts[j], "inline": true});
to
items.push({"value": parts[j], "inline": true});
(3) Change this
items.push({"name": question.concat(" (cont.)"), "value": parts[j], "inline": true});
to
items.push({"value": parts[j], "inline": true});