Vamos a hacer que nuestro bot solo pueda ser utilizado por los miembros de nuestro grupo exclusivo.
Por ejemplo, si un usuario utiliza el comando start
, el bot automáticamente verifica que este sea miembro del grupo especificado. Si lo es, continúa el flujo de la conversación normalmente, si no, despliega un mensaje informando al usuario que no está autorizado para acceder.
Esta solución la encontré porque necesité crear esa funcionalidad antes mencionada, pero los bots de Telegram, a diferencia de los grupos, no permiten establecerse como privados. Tampoco puede restringirse el uso a través de un link, de referidos o generado por el propio bot. No, en Telegram los bots simplemente están ahí y cualquiera puede iniciarlos. Por tanto, nuestra solución debe venir después de iniciarse el bot.
Requisitos para ejecutar este código y términos comunes
El siguiente ejemplo está creado con la librería python-telegram-bot en su versión 13.11 y Python 3.9.6.
Actualización: Una actualización es recibida por el bot siempre que se interactúa con él, puede ser a través de un mensaje, un comando o lo que sea.
Petición: Una petición de datos a los servidores de Telegram.
Implementación
Lo primero es añadir el bot al grupo que queremos 'vigilar', por así decirlo. Añadir el bot funciona como añadir cualquier otro usuario.
Una vez añadido, necesitamos capturar el id de ese grupo para usarlo en nuestro código. Para eso le enviamos una actualización, una update al bot desde ese grupo. Puede ser solo enviar un mensaje aleatorio en el grupo o mencionar al bot a través de su nombre de usuario, dependiendo de los ajustes particulares del bot.
Una vez hayamos enviado algo que el bot pueda detectar, podremos revisar la petición a la API de Telegram directamente en nuestro navegador.
Utilizaremos la siguiente URL: https://api.telegram.org/botTOKEN/getUpdates
, donde debes sustituir 'TOKEN' por el token del bot con que estés trabajando. Basta con pegar la URL en nuestro navegador y recibiremos algo así, pero con muchos más datos:
"message": {
"chat": {
"id": -1234567890,
"title": ...,
"type": "group",
...
}
...
}
De esa información que recibimos en formato JSON debemos tomar solo el id dentro del objeto 'chat', que está dentro del objeto 'message'. En el campo 'title' aparecerá el nombre del grupo, así lo identificaremos fácilmente. El id será un número largo precedido por un guión (-
).
Ya tenemos el id del grupo. Si al ingresar a la petición a la API no aparecen todos esos datos, y en su lugar aparece solo un true
la mejor opción es sacar al bot del grupo y volverlo a añadir, y revisar la petición justo después de enviarle la primera actualización.
Ahora sí pasemos a lo divertido, escribir el código.
Esa id que copiamos de la petición la vamos a guardar en una variable.
grupo_exclusivo_id = ”-1234567890”
Ya que queremos detectar si el usuario es miembro desde el principio de la conversación con el bot, vamos a añadir este snippet desde la función que da la bienvenida al usuario.
Pero antes, entendamos cómo maneja python-telegram-bot a los usuarios dentro de la conversación, y dentro del grupo.
En cada actualización que recibe el bot, podemos acceder al usuario que la envió, obteniendo el objeto User
. Esto lo podemos hacer con update.effective_message.from_user
. Una vez obtenido el objeto User
, podemos acceder a sus datos, como su nombre de usuario o si es o no un bot, pero lo que necesitamos aquí es su id de usuario. Para obtenerla solo le añadimos id
al final del código que ya teníamos. Además, claramente, lo guardaremos en una variable. El código final para obtener la id del usuario queda así:
usuario_id = update.effective_message.from_user.id
Este id también será un número largo, pero sin el guión delante. Ahora sí podemos pasar a la función que detecta si el usuario es miembro del grupo.
El método que utilizaremos es getChatMember
. Este tomará como argumentos el id del grupo y del usuario, y devolverá un objeto ChatMember
que a su vez contendrá un estatus.
Los estatus que puede devolver son: creator
, administrator
, member
, left
, kicked
o restricted
. Estos equivalen, respectivamente, al propietario, un administrador, un miembro, un usuario que salió del grupo, un usuario expulsado y un usuario bloqueado.
Entonces, obtengamos el estatus del usuario que interactuó con nuestro bot.
usuario_miembro = context.bot.getChatmember(grupo_exclusivo_id, usuario_id)
print(usuario_miembro.status)
Con esa última línea, podremos ver cómo devuelve el status
del usuario. Ahora, pasemos a verificar que el estatus sea uno de los que queremos. Si el usuario es miembro del grupo su status
será 'creator', 'administrator' o 'member'. Por tanto, podemos usar un simple if
para verificar la igualdad de su status
con alguno de estos. Hay formas más limpias de hacer esto aun dentro de un if
, pero en aras de la rapidez, hágamoslo de esta manera que funciona igual de bien, solo que es un poco más fea.
grupo_exclusivo_id = ”-1234567890”
usuario_id = update.effective_message.from_user.id
usuario_miembro = context.bot.getChatmember(grupo_exclusivo_id, usuario_id)
def iniciar(update, context):
if usuario_miembro.status == 'creator' or usuario_miembro.status == 'administrator' or usuario_miembro.status == 'member':
update.message.reply_text('Hola, bienvenido.')
else:
update.message.reply_text('No estás autorizado para usar este bot.')
¡Y listo! Ya tenemos un bot exclusivo para nuestro grupo exclusivo.
Un detalle a tener en cuenta: la mejor opción es hacer al bot administrador del grupo, de lo contrario puede tener problemas al detectar el estatus de los administradores, en estos casos les niega el acceso aunque sigan estando en el grupo.
A la hora de debuguear puede serte útil ver directamente en una petición el estatus de un miembro. Puedes hacerlo a través de la siguiente URL:
https://api.telegram.org/botTOKEN/getChatMember?chat_id=CHATID&user_id=USERID/
Conclusiones
Necesitaremos trabajar con los id constantemente al crear bots de Telegram, así que es muy buena idea aprender a manejarlos. Además, el trabajo con grupos es también muy útil y abre un mundo de posibilidades.
Espero que te haya sido útil e instructiva esta guía. Si lo deseas puedes contactarme en Telegram o Twitter. !Espero escuchar de ti!
Todo bien. Pero hay un error, grupo_exclusivo_id debe estar como int no como str, solamente podrá estar como str si es un "@username", osea si es un grupo/canal público.
Solución:
grupo_exclusivo_id = -1234567890
Ahora probé y de las dos formas hizo lo que debía. En mi código lo tengo así como está ahí, pero le quité las comillas y lo detectó sin problema. Curioso.
Oh... 😶🤔 que extraño a mi realmente no me funcionaba de esa manera... que cosas 😅🤣.
Igualmente, muy buen post.
Es raro la verdad 😅, pero bueno, así nos ahorramos unos cuantos
TypeError
jajaAh y gracias por el feedback