DevAlejandre DevAlejandre Agenda gratis

Telegram · Google Sheets

Crea tu bot de Telegram para registrar gastos automáticamente en Google Sheets

Escribe /gasto 250 comida o /gasto 120 gasolina y se guardará en tu hoja con fecha, monto, categoría y nota. Zero servidores: todo con Google Apps Script.

1) Estructura de la hoja

Crea una hoja de cálculo llamada Gastos con una pestaña Movimientos (fila 1 = encabezados):

2) BotFather: crea tu bot

  1. En Telegram, abre @BotFather → envía /newbot.
  2. Elige nombre y usuario, copia el TOKEN (guárdalo).
  3. Opcional: en /setprivacy pon DISABLED (para recibir todos los mensajes del chat).

3) Apps Script: Web App + código

  1. En tu Google Sheet: Extensiones → Apps Script.
  2. Cambia el nombre del proyecto a telegram-gastos.
  3. Pega este código en Code.gs y ajusta las constantes SHEET_ID, SHEET_NAME y ALLOWED_USERS:
/** CONFIG **/
const TELEGRAM_TOKEN   = 'TU_TOKEN_DE_BOTFATHER';
const SHEET_ID        = 'TU_ID_DE_SPREADSHEET';
const SHEET_NAME      = 'Movimientos';
const TIMEZONE        = 'America/Mexico_City';
/** Usuarios permitidos (username sin @ o chat_id numérico). Deja [] para permitir a cualquiera. **/
const ALLOWED_USERS   = ['tu_usuario']; // p.ej. ['diegoalejandre', 123456789]

/** Punto de entrada del Webhook (POST desde Telegram) **/
function doPost(e) {
  try {
    const update = JSON.parse(e.postData.contents);
    if (!update.message) return ContentService.createTextOutput('ok');

    const msg   = update.message;
    const chat  = msg.chat;
    const text  = (msg.text || '').trim();
    const uname = (msg.from.username || String(chat.id)).toString();

    if (!isAllowed(uname)) {
      sendMessage(chat.id, '⛔ No estás autorizado para usar este bot.');
      return ContentService.createTextOutput('forbidden');
    }

    if (text.startsWith('/start')) {
      sendMessage(chat.id, '¡Hola! Usa:\n/gasto <monto> <categoria> [nota opcional]\nEj.: /gasto 250 comida taquitos');
      return ContentService.createTextOutput('ok');
    }

    if (text.startsWith('/gasto')) {
      const { ok, error, data } = parseGasto(text);
      if (!ok) {
        sendMessage(chat.id, 'Formato inválido. Ej.: /gasto 120 gasolina nota opcional');
        return ContentService.createTextOutput('bad');
      }
      const saved = appendRow(uname, data.monto, data.categoria, data.nota);
      sendMessage(chat.id, saved ? '💾 Registrado ✅' : '⚠️ No se pudo guardar.');
      return ContentService.createTextOutput('ok');
    }

    sendMessage(chat.id, 'Comando no reconocido. Usa /gasto o /start.');
    return ContentService.createTextOutput('ok');

  } catch (err) {
    console.error(err);
    return ContentService.createTextOutput('error');
  }
}

/** Helpers **/
function isAllowed(uname) {
  if (!ALLOWED_USERS.length) return true;
  return ALLOWED_USERS.map(String).includes(String(uname));
}

function parseGasto(text) {
  // /gasto 250 comida tacos al pastor
  const parts = text.split(/\s+/).slice(1); // quita "/gasto"
  const monto = Number(parts[0]?.replace(',', '.'));
  const categoria = parts[1];
  const nota = parts.slice(2).join(' ') || '';
  if (!monto || !categoria) return { ok:false, error:'Formato', data:null };
  return { ok:true, data:{ monto, categoria, nota } };
}

function appendRow(uname, monto, categoria, nota) {
  const ss = SpreadsheetApp.openById(SHEET_ID);
  const sh = ss.getSheetByName(SHEET_NAME);
  if (!sh) throw new Error('No existe la pestaña ' + SHEET_NAME);
  const now = new Date();
  const fecha = Utilities.formatDate(now, TIMEZONE, 'yyyy-MM-dd HH:mm:ss');
  sh.appendRow([fecha, '@' + uname, monto, categoria, nota]);
  return true;
}

function sendMessage(chatId, text) {
  const url = 'https://api.telegram.org/bot' + TELEGRAM_TOKEN + '/sendMessage';
  const payload = { chat_id: chatId, text: text };
  const params = { method:'post', contentType:'application/json', payload: JSON.stringify(payload), muteHttpExceptions:true };
  const res = UrlFetchApp.fetch(url, params);
  return res.getResponseCode() === 200;
}

/** Utilidad para probar localmente el parser */
function _testParser() {
  console.log(parseGasto('/gasto 199.90 super verdura y leche'));
}

Publica como Web App: Deploy → New deployment → tipo Web appExecute as: MeWho has access: Anyone → Deploy. Copia la URL del Web App.

4) Conecta el Webhook

  1. Abre en el navegador (reemplazando TOKEN y URL codificada):
    https://api.telegram.org/botTOKEN/setWebhook?url=URL_WEB_APP
  2. Debe responder {"ok":true,...}. Listo, Telegram enviará los mensajes al Web App.
  3. Para ver errores, revisa Apps Script → Executions (logs).

5) Comandos y ejemplos

6) Seguridad, límites y log

¿Prefieres que lo implemente y te lo deje con dashboard?

Configuro el bot, tu Sheet con pivotes y un dashboard simple para ver gastos por categoría/mes.


← Post anterior
Publicado: 7 junio 2025 · Lectura 6–9 min
Siguiente post →