En una publicación anterior, aprendimos a crear y alojar un bot de Telegram gratis y al finalizar prometí que le agregaríamos funcionalidades interesantes. Pues esta es una de ellas, la cual te permitirá informar de tus nuevas publicaciones (tanto de Blogger como WordPress) a tus suscriptores en tus canales de Telegram.
Requisitos
- Haber completado el tutorial parar crear el bot de Telegram.
- Crear un canal de Telegram (puede ser público o privado).
Configurar el worker
Vamos a hacer algunos cambios en las configuraciones en Cloudflare, ya que necesitamos preparar todo antes de implementar los cambios en el código.
Crear un espacio de nombres KV
Primero, en el menú izquierdo, ve a "Workers y Pages", selecciona "KV", haz clic en "Crear espacio de nombres", dale un nombre y guarda los cambios.
Crear variables de entorno
Ve al apartado Información general de Workers y Pages, da clic sobre tu worker y dirígete a la Configuración. Aquí selecciona la sección Variables y en "Variables de entorno", haz clic en "Editar variables":
En el campo "Nombre de variable" escribe CURRENT_FEED y en el campo "Valor" agrega la url de un feed de Blogger o WordPress, por ejemplo:
https://www.example.com/feeds/posts/default?alt=json&max-results=1
https://www.example.com/wp-json/wp/v2/posts?per_page=1
Guarda los cambios y en la misma sección desplázate hacia abajo hasta encontrar "Enlaces de espacios de nombres de KV". Agrega una nueva variable en donde el campo Nombre de variable debe ser KV_STORAGE_FEED y en el campo "Valor" selecciona el espacio de nombres que creaste anteriormente, por último guarda los cambios.
Configurar Triggers / Activadores
Tras finalizar la configuración de las variables, dirígete a la pestaña "Activadores", desplázate hacia abajo hasta encontrar "Activadores de Cron" y haz clic en "Agregar activador".
Solo debes especificar el intervalo de tiempo en el que quieres que se ejecute el activador, por ejemplo, si especificas 30 minutos el bot buscará si hay nuevas publicaciones cada 30 minutos.
Agregar el código
Si hiciste todo correctamente, felicidades, ya casi terminamos. Ahora solo vamos a editar el código precionando el botón "Edición rápida", recuerda que aquí ya tenemos un código que corresponde al tutorial anterior.
Nuevas variables
En la primera línea del código, haz un espacio y agrega las siguientes variables que harán referencia a las variables de entorno que configuramos anteriormente.
const FEED = CURRENT_FEED
const KV_NAMESPACE = KV_STORAGE_FEED
Función para obtener canales
El trabajo de esta función será de obtener y parsear el objeto, que almacena el ID de todos los canales en donde el bot se haya agregado como administrador. Es importante para más adelante:
// Obtiene los canales de KV
async function getChannels () {
let channels = await KV_NAMESPACE.get('channels') || {}
// Si channels no es un objeto, convertirlo
if (typeof channels !== 'object') {
channels = JSON.parse(channels)
}
return channels
}
Función para gestionar la lista de canales
Cuando el bot es agregado a un canal, esta función se encargará de incluir el ID junto con el nombre del canal a nuestro espacio de nombres. Si el bot es eliminado de un canal, ese ID también será borrada del registro.
// Maneja el estado de miembro
// https://core.telegram.org/bots/api#chatmember
async function manageMember (member) {
const chatTitle = member.chat.title
const chatId = member.chat.id
const chatType = member.chat.type
// bot status (administrator, kicked, left, member, restricted, creator)
const status = member.new_chat_member.status
// Si el tipo de chat no es "channel", no hacer nada
if (chatType !== 'channel') {
return
}
// Obtener los canales de KV o crear un objeto vacío
const channels = await getChannels()
// Si el bot es "administrator", agregar y almacenarlo en KV
if (status === 'administrator') {
channels[chatId] = chatTitle
await KV_NAMESPACE.put('channels', JSON.stringify(channels))
}
// Si el estado es "left" o "kicked", eliminar el canal de KV
if (status === 'left' || status === 'kicked') {
delete channels[chatId]
await KV_NAMESPACE.put('channels', JSON.stringify(channels))
}
}
Actualizar la funcion onUpdate
En el tutorial anterior ya habíamos creado esta función, pero para esta característica será necesario modificarla. Busca la función onUpdate()
y reemplázala con esta nueva versión:
async function onUpdate (update) {
// Si la actualización contiene un mensaje, se llama a la función "onMessage".
if ('message' in update) {
await onMessage(update.message)
}
// Si es un estado de miembro, se llama a la función "manageMember".
if ('my_chat_member' in update) {
await manageMember(update.my_chat_member)
}
}
Función para gestionar el feed
Esta función obtiene el feed, diferencia si es de Blogger o WordPress, obtiene la última publicación y la envia a tus canales. En el proceso, también se almacenará el ID de la última publicación en el espacio de nombres KV para futuras comparaciones.
// Manejar las actualizaciones de manera asíncrona
async function handleScheduled (event) {
try {
// Obtener el enlace de la entrada (Solo Blogger)
function getLink (links) {
for (const link of links) {
if (link.rel === 'alternate') {
return link.href
}
}
}
// Obtener el feed de Blogger o WordPress
const feed = await fetch(FEED)
const data = await feed.json()
// Verificar si el feed es de Blogger
const isBlogger = data.feed
// Obtener la ultima entrada del feed
const newEntry = isBlogger ? data.feed.entry[0] : data[0]
// Obtener el ID de la entrada más reciente y del KV
const newEntryId = isBlogger ? newEntry.id.$t : newEntry.id
const getEntryId = await KV_NAMESPACE.get('currentEntryId')
// Convertir la ID de la entrada en un número (Solo WordPress)
const currentEntryId = isBlogger ? getEntryId : Number(getEntryId)
// Si hay un nuevo ID de entrada, enviar a todos los canales
if (!currentEntryId || newEntryId !== currentEntryId) {
// Actualizar la ID de la entrada almacenado en KV
await KV_NAMESPACE.put('currentEntryId', newEntryId)
// Obtener el título y el enlace de la entrada
const title = isBlogger ? newEntry.title.$t : newEntry.title.rendered
const link = isBlogger ? getLink(newEntry.link) : newEntry.link
// Establecer el texto del mensaje
const messageText = `${title}\n${link}`
const channels = await getChannels()
// Enviar mensajes a todos los canales
for (const channelId of Object.keys(channels)) {
await sendPlainText(channelId, messageText)
}
}
} catch (error) {
console.error('Error al obtener o procesar el feed:', error)
}
}
Ahora, solo nos falta llamar a la función handleScheduled
en el evento scheduled
, para ello, agrega el siguiente código debajo de la función anterior:
// Ejecuta en intervalos regulares para enviar actualizaciones
addEventListener('scheduled', event => {
event.waitUntil(handleScheduled(event))
})
Pulsa el botón "Guardar e implementar" y ya hemos terminado. Ahora solo tienes que agregar tu bot como administrador a un canal de telegram para que este empiece a enviar tus actualizaciones.
Conclusión
Esta es una excelente, cómoda y gratuita forma de informar a tus suscriptores de tus nuevas publicaciones sin tener que llenarlos de correos electrónicos. Si quieres ver este código funcionando, puedes suscribirte a mi canal de Telegram y comprobar las actualizaciones.
Si tienes alguna duda o sugerencia, no dudes en dejarla en los comentarios, estaré encantado de ayudarte. No olvides compartir este aporte en tus redes sociales, siempre lo agradezco. Muchas gracias por pasar.