Skip to content

Instantly share code, notes, and snippets.

@baruchiro
Last active March 22, 2023 17:43
Show Gist options
  • Save baruchiro/4bab7004a05292b824fbe5f6d0bfdb2e to your computer and use it in GitHub Desktop.
Save baruchiro/4bab7004a05292b824fbe5f6d0bfdb2e to your computer and use it in GitHub Desktop.
Google Apps Script reuse
function doPost(e) {
log("Received doPost")
try {
const { chatId, text, update } = getUpdate(e)
if (myChatId !== chatId)
return sendMessage(chatId, `You are not authorized`)
if (!isDocument(update))
return sendMessage(chatId, `message is without document`)
const fileUrl = HandleTelegrmFile(update.message.document, new Date(update.message.date * 1000))
replyToSender(update, fileUrl)
} catch (e) {
log('error', JSON.stringify(e, Object.getOwnPropertyNames(e)))
sendMessage(myChatId, JSON.stringify(e, Object.getOwnPropertyNames(e)))
throw e
}
}
/**
* Every time you changing something related to the Bot webhook, you have to
* 1. Deploy as Webapp
* 2. Copy the deployment URL
* 3. Paste it here
* 4. Run the setWebhook function
*/
const token = '<<Telegram Token>>'
const url = 'https://script.google.com/macros/s/*********/exec'
const myChatId = <<your chat id>>;
const telegramURL = `https://api.telegram.org/bot${token}`
const telegramFileUrl = `https://api.telegram.org/file/bot${token}`
function setWebhook() {
const res = request('setWebhook', { url })
Logger.log(res)
}
function request(method, data) {
var options = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(data)
};
var response = UrlFetchApp.fetch(`${telegramURL}/${method}`, options);
if (response.getResponseCode() == 200) {
return JSON.parse(response.getContentText());
}
return false;
}
/**
* https://core.telegram.org/bots/api#update
*
* @return {{
* chatId: number,
* text: string,
* update: Update
* }}
*/
function getUpdate(doPostE) {
// Make sure to only reply to json requests
if (doPostE.postData.type == "application/json") {
// Parse the update sent from Telegram
const update = JSON.parse(doPostE.postData.contents);
const text = update.message.text
log(`Message: ${text}`)
return {
chatId: update.message.from.id,
text,
update
}
}
}
function replyToSender(update, text) {
sendMessage(update.message.from.id, text)
}
function sendMessage(chatId, text, parse_mode) {
return request('sendMessage', {
'chat_id': chatId,
'text': text,
parse_mode,
});
}
/**
* @param update {Update}
*/
function isDocument(update) {
return !!update.message.document
}
function DownloadFile(fileId) {
const response = UrlFetchApp.fetch(`${telegramURL}/getFile?file_id=${fileId}`);
if (response.getResponseCode() != 200) {
log('getFile', 'response', response.getResponseCode())
throw new Error()
}
const parsed = JSON.parse(response.getContentText())
log('parsed', parsed)
const urlFile = `${telegramFileUrl}/${parsed.result["file_path"]}`;
log('urlFile', urlFile)
const resa = UrlFetchApp.fetch(urlFile);
const blob = resa.getBlob();
return blob;
}
/*
callback url:
Click on File > Project properties and copy the value from 'Project key'
your callback url will be:
https://script.google.com/macros/d/[Project key]/usercallback
copy this url and paste it in your app on the Twitter developer dashboard:
https://developer.twitter.com/
you should also paste it in the code here, line 18;
*/
var consumer_key = "****"
var consumer_secret = "****"
var project_key = "****" // File > Project properties > Project key
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Twitter')
.addItem('Tweet test text', 'sendTestTweet')
.addItem('revoke', 'authorizationRevoke')
.addItem('show my callBack url', 'getCallBackUrl')
.addToUi();
msgPopUp('<p>Click on Tools > Script Editor and follow instructions</p>');
};
function sendTestTweet() {
doTweet("hello world");
}
function authorizationRevoke() {
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.deleteProperty('oauth1.twitter');
msgPopUp('<p>Your Twitter authorization credentials have been deleted. You\'ll need to re-run "Send a Test Tweet" to reauthorize before you can start posting again.');
}
function getTwitterService() {
var service = OAuth1.createService('twitter');
service.setAccessTokenUrl('https://api.twitter.com/oauth/access_token');
service.setRequestTokenUrl('https://api.twitter.com/oauth/request_token');
service.setAuthorizationUrl('https://api.twitter.com/oauth/authorize');
service.setConsumerKey(consumer_key);
service.setConsumerSecret(consumer_secret);
service.setCallbackFunction('authCallback');
service.setPropertyStore(PropertiesService.getScriptProperties());
const x = PropertiesService.getScriptProperties();
return service;
}
function authCallback(request) {
var service = getTwitterService();
var isAuthorized = service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success! You can close this page.');
} else {
return HtmlService.createHtmlOutput('Denied. You can close this page');
}
}
function msgPopUp(msg) {
var content = '<div style="font-family: Verdana;font-size: 22px; text-align:left; width: 95%; margin: 0 auto;">' + msg + '</div>';
var htmlOutput = HtmlService
.createHtmlOutput(content)
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(600)
.setHeight(500);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, ' ');
}
function twitterAPIRequest(url, parameters) {
var service = getTwitterService();
if (!service.hasAccess()) {
var authorizationUrl = service.authorize();
msgPopUp('<p>Please visit the following URL and then re-run "Send a Test Tweet": <br/> <a target="_blank" href="' + authorizationUrl + '">' + authorizationUrl + '</a></p>');
return;
}
var result = service.fetch("https://api.twitter.com" + url, parameters);
return JSON.parse(result.getContentText());
}
/**
* @param tweet {string}
* @return {string}
*/
function doTweet(tweet) {
var id_str = "";
var url = "/1.1/statuses/update.json";
var payload = "status=" + fixedEncodeURIComponent(tweet);
var parameters = {
"method": "POST",
"escaping": false,
"payload": payload
};
try {
var result = twitterAPIRequest(url, parameters);
id_str = result.id_str;
}
catch (e) {
Logger.log(e.toString());
throw e
}
return id_str;
}
/**
* @param tweet {string}
* @param status_id {string|number}
* @return {string}
*/
function doReply(tweet, status_id) {
var url = '/1.1/statuses/update.json';
var payload = {
"in_reply_to_status_id": status_id,
"auto_populate_reply_metadata": true,
"status": tweet
}
var parameters = {
"method": "POST",
"escaping": false,
"payload": payload
};
const result = twitterAPIRequest(url, parameters);
Logger.log(result);
return result.id_str;
}
function fixedEncodeURIComponent(str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
@mbino94
Copy link

mbino94 commented Apr 30, 2022

Hello sir.
im facing an issue , hope you can help
every time i Create a variable that contains a special character like ( _ or @ )my script stops working
for example:
var target = contents.massage.reply_to_message.from.id;
if add this line to my script the script stops working

@mbino94
Copy link

mbino94 commented Apr 30, 2022

my full script is here

function setWebhook() { 
  var url = telegramUrl + "/setWebhook?url=" + webAppUrl;
  var response = UrlFetchApp.fetch(url);
}

function sendMessage(id, text,) {
  var url = telegramUrl + "/sendMessage?chat_id=" + id + "&text=" + text;
  sponse = UrlFetchApp.fetch(url);
}

function doPost(e) {
  var contents = JSON.parse(e.postData.contents);
  var id = contents.message.from.id;
  var text = contents.message.text;
  `var target = contents.massage.reply_to_message.from.id;`
  
 if (text.includes("/who")) {
    sendMessage(id, "it is " + target+ " :) " );

@baruchiro
Copy link
Author

What do you mean "stops working"?

@mbino94
Copy link

mbino94 commented May 1, 2022

What do you mean "stops working"?

It doesn't send a msg to telegram

I've noticed that even if comment out that line, the script doesn't work

Even if am sending another text message
Like sending the text back

if (text.includes("/who")) { sendMessage(id, "it is " + text + " :) " );

I must delete the line
var target = contents.massage.reply_to_message.from.id;
So it starts working again

@baruchiro
Copy link
Author

Probably you have a bug in that line. What I'm doing is using try catch inside the doPost, and sending the caught error to me in Telegram, or printing it into the sheet.

@mbino94
Copy link

mbino94 commented May 6, 2022

Probably you have a bug in that line. What I'm doing is using try catch inside the doPost, and sending the caught error to me in Telegram, or printing it into the sheet.

ive tried to catch the error
and got that .from.id is undefined which are in the line var target = contents.massage.reply_to_message.from.id;

but they are defined in the object as you see in the screenshot
Screenshot 2022-05-06 174550

@baruchiro
Copy link
Author

Don't know, it is more related to the Telegram API than Google Sheets.

https://stackoverflow.com/a/72070240/839513

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment